Hibernate从不同的会话更新 [英] Hibernate updating from different sessions

查看:83
本文介绍了Hibernate从不同的会话更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



到现在为止,我试图将单独的类中的所有数据库代码分开,例如
TableTeam或TableMember,它们的方法类似于 .getAllTeams() .updateTeam(Team t)。这些方法充当他们执行的sql查询的包装。

现在使用hibernate时,我试图尽可能地保留界面,只是将SQL查询更改为主要工作的休眠功能。
有一个例外:更新元素。

  team = new Team(-1,Team Name,Collections。 <会员> emptySet()); 

@Test
public void testUpdateTeam()抛出异常{
table.addTeam(team);
team.setName(New Name);
table.updateTeam(team);
Team f = table.getAllTeams()。get(0);
Assert.assertEquals(team,f);
}

会导致以下异常:

  org.hibernate.LazyInitializationException:无法延迟初始化角色集合:ch.tiim.sco.database.model.Team.members,无法初始化代理 - 无会话
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)
在org.junit.Assert.isEqu als(Assert.java:131)
at org.junit.Assert.equalsRegardingNull(Assert.java:127)
at org.junit.Assert.assertEquals(Assert.java:111)
在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();

$ / code>

对于 .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)
私人字符串名称;
@ManyToOne
@JoinColumn(name =club_id)
私人俱乐部俱乐部;
@ManyToMany
@JoinTable(name =team_members,
joinColumns = {@JoinColumn(name =team_id)},
inverseJoinColumns = {@JoinColumn(name = member_id)}

private java.util.Set< Member>成员;

//我剥离了构造函数和setters / getters
}

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



编辑这里是hibernate配置

 <?xml version ='1.0'encoding ='utf-8'?> 
<!DOCTYPE hibernate-configuration PUBLIC
- // Hibernate / Hibernate配置DTD 3.0 // EN
http://www.hibernate.org/dtd/hibernate-configuration -3.0.dtd>

< hibernate-configuration>
< session-factory>
<! - 数据库连接设置 - >
< 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连接池(使用内置) - >
< property name =connection.pool_size> 1< / property>
<! - SQL方言 - >
< property name =dialect> org.hibernate.dialect.H2Dialect< / property>
<! - 启用Hibernate的自动会话上下文管理 - >
< property name =current_session_context_class>线程< / property>
<! - 禁用第二级缓存 - >
< property name =cache.provider_class> org.hibernate.cache.internal.NoCacheProvider< / property>
<! - 将所有执行的SQL回复到stdout - >
<! - - property name =show_sql> true< / property - >
<! - 在启动时删除并重新创建数据库模式 - >
< property name =hbm2ddl.auto>建立< / property>
< / session-factory>
< / hibernate-configuration>


解决方案

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

  SessionFactory sf = null; 
Session s = null;
SessionHolder持有者= null;

@Override
保护无效onSetUp()抛出异常{
System.out.println(On SetUP ----);
sf =(SessionFactory)beanFactory.getBean(sessionFactory);
s = sf.openSession();
TransactionSynchronizationManager.bindResource(sf,新的SessionHolder(s));

$ b $ @覆盖
保护无效onTearDown()抛出异常{
System.out.println(on onTearDown ----);
//取消绑定并关闭会话。
持有人=(SessionHolder)TransactionSynchronizationManager.getResource(sf);
s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sf);
SessionFactoryUtils.releaseSession(s,sf);
//在此处拆除代码
}

如果您不想再小心关于LazyInitialisationException阅读这个,它很好地解释了会发生什么,以及如何解决这个问题。

I am porting a java fat client from JDBC SQLite to Hibernate H2.

Until now I tried to separate all my database code in separate classes, like TableTeam or TableMember, which have methods like .getAllTeams() or .updateTeam(Team t). These methods acted as a wrapper around their sql queries they executed.

Now with hibernate I tried to leave the interface as good as possible and just change the SQL queries to hibernate functions, which mostly works. With one exception: updating elements.

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);
}

results in the following exception:

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)

The code for .updateTeam(Team t) is the following:

public void updateTeam(Team t) {
    Session s = sessionFactory.getCurrentSession();
    s.beginTransaction();
    s.update(t);
    s.getTransaction().commit();
}

And the same for .addTeam(Team t) but s.save(t) instead of s.update(t)

And Team looks like this:

@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
}

Now how do I get rid of this error, without guaranteeing that every call to hibernate is from the same thread?

Edit Here is the hibernate configuration

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

解决方案

For Junit testcases you need to bind an opened Session to the current 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
}

If you want to no more care about LazyInitialisationException read this, its well explain what happens, and how to resolve the problem definitely

这篇关于Hibernate从不同的会话更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆