【问题标题】:Hibernate deletes relations in a @ManyToMany relationsship with lazy loadingHibernate 使用延迟加载删除 @ManyToMany 关系中的关系
【发布时间】:2013-08-28 06:47:15
【问题描述】:

我在使用休眠删除两个对象之间的关系时遇到了问题。第一个是:

    @Entity
    @Table(name="A")
    public class A extends AbstractBO{

        private List<B> b;

        @Override
        @Id
        public String getId(){
            return id;
        }

        public void setId(String id) {
        this.id = id;
        }

        @ManyToMany(targetEntity=B.class, fetch=FetchType.LAZY)
        @JoinTable(name="A_B", joinColumns={@JoinColumn(name="A_id")},inverseJoinColumns={@JoinColumn(name="B_id")})
        public List<B> getBs() {
            return b;
        }

        public void setBs(List<B> b) {
        this.b = b;
        }
    }

第二个:

@Entity
@Table(name="B")
public class B extends AbstractBO {

    private List<A> a;

    @Override
    @Id
    public String getId(){
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @ManyToMany(targetEntity=A.class, fetch=FetchType.LAZY, mappedBy="b")
    public List<A> getAs() {
        return a;
    }

    public void setAs(List<A> a) {
        this.a = a;
        }
}

我的 hibernate.cfg.xml 是:

<hibernate-configuration>
  <session-factory>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">****</property>
    <property name="hibernate.connection.release_mode">auto</property>
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="show_sql">true</property>
    <property name="hibernate.enable_lazy_load_no_trans">true</property>
    <property name="hibernate.generate_statistics">false</property>

    <property name="transaction.factory_class">
      org.hibernate.transaction.JDBCTransactionFactory
    </property>
    <property name="hibernate.cache.provider_class">
      org.hibernate.cache.HashtableCacheProvider
    </property>

    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">2</property>
    <property name="current_session_context_class">thread</property>

    <property name="hibernate.hbm2ddl.auto">update</property>

    <mapping class="de.test.A"/>
    <mapping class="de.test.B"/>    

  </session-factory>
</hibernate-configuration>

到目前为止,一切正常。可以保存、更新、删除和加载持久存在于数据库中的所有对象及其所有子对象。如果我正在加载A 类型的对象,在前端调用getBs(),我会得到正确的对象及其所有子对象。但是休眠会执行“休眠:从 B_id= 的 A_B 中删除?”紧跟在 SELECT 语句之后。这将删除对象与其子对象之间的所有关系。 如果我将FetchType 的B 更改为“EAGER”,一切正常。看来,休眠消除了一个事实,即没有调用子对象的getAs()。

我还尝试将B 类的getAs() 更改为:

@JoinTable(name="A_B", joinColumns={@JoinColumn(name="B_id")}, inverseJoinColumns={@JoinColumn(name="A_id")})
    public List<A> getAs() {[...]

顺便说一句,我正在使用:

  • 休眠 4.2.4 最终版
  • JSF 2.0
  • JPA 2.0

我已经阅读了许多相关文章并尝试了 Cascade 等不同的建议。我还考虑过在 B 的构造函数中调用 getAs(),但所有这些都没有解决我的问题。

在调试我的应用程序时,我在 B 类的 getter 中添加了一行:

public List<A> getAs() {
    if(a!=null) a.size();
    return a;
}

呼叫a.size() 不会改变任何事情。所以我很困惑,因为一切都突然发生了。所以作为一个结论,我的应用程序现在可以使用这个“修复”。但如果有人能给我一个更通用的解决方案,我将不胜感激。

【问题讨论】:

    标签: java mysql hibernate jpa


    【解决方案1】:

    由于您启用了hibernate.enable_lazy_load_no_trans 并且该错误仍然存​​在,我猜您是HHH-7971 的受害者。我无法为您提供适当的解决方案,如果该行为是由此错误引起的,您可以使用解决方法来修复它。

    我猜a.size() 解决了这个问题,因为 Hibernate 代理在那一刻被初始化。所以使用Hibernate.initialize(a)会更合适。我也不会在 getter 中这样做,而是在你调用 getter 的地方。

    【讨论】:

    • 为什么推荐使用 Hibernate.initialize(a) ?我会尝试你的建议,之后会更新这个问题。
    • 一方面它更具可读性,每个人都知道当他阅读该行时发生了什么,另一方面您不必进行null检查。
    • 不幸的是 Hibernate.initialize(a) 不能解决这个问题。我在 getter 中实现了它,因为我的应用程序确实直接从前端调用了该 getter。在运行您的建议时,关系再次被删除。
    • 顺便说一句。我已经认识到,如果 hibernate 在 SELECT 之后删除所有关系并且我将在父对象上调用 saveOrUpdate ,则所有关系都会再次插入。
    • 对不起,Hibernate.initialize 本身并没有初始化 a,但它初始化了 a 的每个元素(它们是代理)。所以我认为最合适的方式是拨打a.size()。每次选择后删除并重新插入并不是解决此问题的好方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多