从不同的会话休眠更新
Hibernate updating from different sessions
我正在将 java 胖客户端从 JDBC SQLite 移植到 Hibernate H2。
直到现在我都尝试将所有数据库代码分开 类,比如
TableTeam 或 TableMember,它们具有 .getAllTeams()
或 .updateTeam(Team t)
等方法。这些方法充当了它们执行的 sql 查询的包装器。
现在使用 hibernate,我尝试尽可能保留界面,只是将 SQL 查询更改为休眠函数,这在大多数情况下都有效。
除了一个例外:更新元素。
team = new Team(-1, "Team Name", Collections.<Member>emptySet());
@Test
public void testUpdateTeam() throws Exception {
table.addTeam(team);
team.setName("New Name");
table.updateTeam(team);
Team f = table.getAllTeams().get(0);
Assert.assertEquals(team, f);
}
导致以下异常:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ch.tiim.sco.database.model.Team.members, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:576)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:215)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:156)
at org.hibernate.collection.internal.PersistentSet.size(PersistentSet.java:160)
at java.util.AbstractSet.equals(AbstractSet.java:92)
at org.hibernate.collection.internal.PersistentSet.equals(PersistentSet.java:441)
at ch.tiim.sco.database.model.Team.equals(Team.java:81)
at org.junit.Assert.isEquals(Assert.java:131)
at org.junit.Assert.equalsRegardingNull(Assert.java:127)
at org.junit.Assert.assertEquals(Assert.java:111)
at org.junit.Assert.assertEquals(Assert.java:144)
at ch.tiim.sco.database.TableMemberTest.testEditTeam(TableMemberTest.java:45)
.updateTeam(Team t)
的代码如下:
public void updateTeam(Team t) {
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
s.update(t);
s.getTransaction().commit();
}
.addTeam(Team t)
也是如此,但 s.save(t)
而不是 s.update(t)
团队看起来像这样:
@Entity
@Table(name = "team")
public class Team implements Model {
@Id
@GeneratedValue
@Column(name = "team_id")
private int id;
@Column(name = "name")
private String name;
@ManyToOne
@JoinColumn(name = "club_id")
private Club club;
@ManyToMany
@JoinTable(name = "team_members",
joinColumns = {@JoinColumn(name = "team_id")},
inverseJoinColumns = {@JoinColumn(name = "member_id")}
)
private java.util.Set<Member> members;
//I stripped the constructor and the setters/getters
}
现在如何消除这个错误,但不能保证对休眠的每次调用都来自同一个线程?
编辑这里是休眠配置
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.h2.Driver</property>
<!--property name="connection.url">jdbc:h2:./test</property-->
<property name="connection.username">user</property>
<property name="connection.password">pass</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<!--property name="show_sql">true</property-->
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
</session-factory>
</hibernate-configuration>
你能post你的hibernate.cfg吗?我猜测?您没有配置的会话上下文:
例如
线程
对于 Junit 测试用例,您需要将打开的会话绑定到当前线程。
SessionFactory sf = null;
Session s = null;
SessionHolder holder = null;
@Override
protected void onSetUp() throws Exception {
System.out.println("On SetUP----");
sf = (SessionFactory) beanFactory.getBean("sessionFactory");
s = sf.openSession();
TransactionSynchronizationManager.bindResource(sf, new SessionHolder(s));
}
@Override
protected void onTearDown() throws Exception {
System.out.println("On onTearDown----");
// unbind and close the session.
holder = (SessionHolder)TransactionSynchronizationManager.getResource(sf);
s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sf);
SessionFactoryUtils.releaseSession(s, sf);
// teardown code here
}
如果你不想再关心 LazyInitialisationException 阅读this,它很好地解释了发生了什么,以及如何解决问题
我正在将 java 胖客户端从 JDBC SQLite 移植到 Hibernate H2。
直到现在我都尝试将所有数据库代码分开 类,比如
TableTeam 或 TableMember,它们具有 .getAllTeams()
或 .updateTeam(Team t)
等方法。这些方法充当了它们执行的 sql 查询的包装器。
现在使用 hibernate,我尝试尽可能保留界面,只是将 SQL 查询更改为休眠函数,这在大多数情况下都有效。 除了一个例外:更新元素。
team = new Team(-1, "Team Name", Collections.<Member>emptySet());
@Test
public void testUpdateTeam() throws Exception {
table.addTeam(team);
team.setName("New Name");
table.updateTeam(team);
Team f = table.getAllTeams().get(0);
Assert.assertEquals(team, f);
}
导致以下异常:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ch.tiim.sco.database.model.Team.members, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:576)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:215)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:156)
at org.hibernate.collection.internal.PersistentSet.size(PersistentSet.java:160)
at java.util.AbstractSet.equals(AbstractSet.java:92)
at org.hibernate.collection.internal.PersistentSet.equals(PersistentSet.java:441)
at ch.tiim.sco.database.model.Team.equals(Team.java:81)
at org.junit.Assert.isEquals(Assert.java:131)
at org.junit.Assert.equalsRegardingNull(Assert.java:127)
at org.junit.Assert.assertEquals(Assert.java:111)
at org.junit.Assert.assertEquals(Assert.java:144)
at ch.tiim.sco.database.TableMemberTest.testEditTeam(TableMemberTest.java:45)
.updateTeam(Team t)
的代码如下:
public void updateTeam(Team t) {
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
s.update(t);
s.getTransaction().commit();
}
.addTeam(Team t)
也是如此,但 s.save(t)
而不是 s.update(t)
团队看起来像这样:
@Entity
@Table(name = "team")
public class Team implements Model {
@Id
@GeneratedValue
@Column(name = "team_id")
private int id;
@Column(name = "name")
private String name;
@ManyToOne
@JoinColumn(name = "club_id")
private Club club;
@ManyToMany
@JoinTable(name = "team_members",
joinColumns = {@JoinColumn(name = "team_id")},
inverseJoinColumns = {@JoinColumn(name = "member_id")}
)
private java.util.Set<Member> members;
//I stripped the constructor and the setters/getters
}
现在如何消除这个错误,但不能保证对休眠的每次调用都来自同一个线程?
编辑这里是休眠配置
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.h2.Driver</property>
<!--property name="connection.url">jdbc:h2:./test</property-->
<property name="connection.username">user</property>
<property name="connection.password">pass</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<!--property name="show_sql">true</property-->
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
</session-factory>
</hibernate-configuration>
你能post你的hibernate.cfg吗?我猜测?您没有配置的会话上下文:
例如 线程
对于 Junit 测试用例,您需要将打开的会话绑定到当前线程。
SessionFactory sf = null;
Session s = null;
SessionHolder holder = null;
@Override
protected void onSetUp() throws Exception {
System.out.println("On SetUP----");
sf = (SessionFactory) beanFactory.getBean("sessionFactory");
s = sf.openSession();
TransactionSynchronizationManager.bindResource(sf, new SessionHolder(s));
}
@Override
protected void onTearDown() throws Exception {
System.out.println("On onTearDown----");
// unbind and close the session.
holder = (SessionHolder)TransactionSynchronizationManager.getResource(sf);
s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sf);
SessionFactoryUtils.releaseSession(s, sf);
// teardown code here
}
如果你不想再关心 LazyInitialisationException 阅读this,它很好地解释了发生了什么,以及如何解决问题