从不同的会话更新Hibernate

时间:2015-08-20 20:00:23

标签: java hibernate lazy-loading

我正在将一个java胖客户端从JDBC SQLite移植到Hibernate H2。

到目前为止,我试图在单独的类中分离所有数据库代码,例如 TableTeam或TableMember,其中包含.getAllTeams().updateTeam(Team t)等方法。这些方法充当了他们执行的sql查询的包装器。

现在有了hibernate,我试图让界面尽可能好,只需将SQL查询更改为hibernate函数,这些函数最常用。 有一个例外:更新元素。

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
}

现在我如何摆脱这个错误,而不保证每次调用hibernate来自同一个线程?

编辑以下是hibernate配置

<?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>

2 个答案:

答案 0 :(得分:0)

你可以发布你的hibernate.cfg吗?我猜测?您没有配置的会话上下文:

E.g 螺纹

答案 1 :(得分:0)

对于Junit测试用例,您需要将打开的Session绑定到当前的Thread。

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,它会很好地解释会发生什么,以及如何解决问题