【问题标题】:Solving issues with unidirectional OneToMany relationship解决单向 OneToMany 关系的问题
【发布时间】:2014-09-03 00:27:26
【问题描述】:

我正在使用遗留代码。我有entity Aentity B 类,但是因为entity B 被很多地方引用,我尽量不对entity B 进行更改。以下是这两个实体的类。 Entity B 有一个外键列,它是entity A 的主键,在数据库表中,外键(aId) 与表b(id) 的许多主键相关联。

我需要的是 A 的集合(例如,ID 范围在 1 - 10000 之间),其中包括当我对 table_a 进行查询时对应于辅助的 B 的集合。当前的实现是首先获取 A 的集合(具有大量行),然后遍历集合中的每个 A,然后调用 dao.findB(aId) 为 A 设置 B 的集合。这会导致多次访问数据库。我尽量减少这次旅行。例如,如果 A 有 50,000 行,dao.findB(aId) 将被调用 50,000 次。

table_b
----------
id   table_a_id
1     2
2     2
3     2
4     3
5     3


 @Entity
 @Table(name = "table_a")
 public class A{
     private static final long serialVersionUID = 1L;

     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @Column(name = "id", unique = true, nullable = false) 
     private Long id;

 }


 @Entity
 @Table(name = "table_b")
 public class B{
     private static final long serialVersionUID = 1L;

     @Id
     @Column(name="id", unique = true, nullable = false)
     @GeneratedValue
     private Long id;

     @Column(name="table_a_id")
     private Long aId;

 }

【问题讨论】:

    标签: hibernate jpa-2.0 hibernate-mapping hibernate-criteria


    【解决方案1】:

    如下所示

    假设您有aid,您想通过它加载Entity B 的集合。

    A a = session.find(A.class,aid); // just some pseudo code
    
    Criteria cr = session.createCriteria(B.class);
    cr.add(Restrictions.eq("aId", aid));
    List<B> results = cr.list();
    

    【讨论】:

    • @user3123690 的回答对你有帮助。
    • 感谢您的回答。我认为我没有对我的问题进行足够的解释。我刚刚更新了它。你能看一下吗?
    • @user3123690 即使您在Entity A 中保留Entity B 的引用,仍然会获取相同的查询。替代方法是根据A id 查询Entity B
    • 'results'是一个B对应的集合,对应于aid。我需要的是 A 的集合(例如,ID 范围在 1 - 10000 之间),其中包括与援助对应的 B 的集合。我认为我不太了解您的回答。
    • 对不起。我不知道怎么问这个问题。我更新了我的问题。希望现在很清楚。
    【解决方案2】:

    在链接How to define unidirectional OneToMany relationship in JPAhttp://en.wikibooks.org/wiki/Java_Persistence/OneToMany 的帮助下,我在不更改实体B 的情况下让它工作。我确实检查了SQL 日志,它节省了过多的数据库访问。

    当我使用以下条件进行查询时,它返回了一个包含 B 集合的 A 集合。

     Criteria criteria = session.createCriteria(A.class).add(Restrictions.in("id", ids)).setFetchMode("bSet", FetchMode.JOIN).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);              
                List<A> result = criteria.list();
    
    
    @Entity
     @Table(name = "table_a")
     public class A{
         private static final long serialVersionUID = 1L;
    
         @Id
         @GeneratedValue(strategy = GenerationType.IDENTITY)
         @Column(name = "id", unique = true, nullable = false) 
         private Long id;
    
         @OneToMany
         @JoinColumn(name="table_a_id", referencedColumnName="id")  
         private Set<B> bSet = new HashSet<B> ();
    
     }
    
    
     @Entity
     @Table(name = "table_b")
     public class B{
         private static final long serialVersionUID = 1L;
    
         @Id
         @Column(name="id", unique = true, nullable = false)
         @GeneratedValue
         private Long id;
    
         @Column(name="table_a_id")
         private Long aId;
    
     }
    

    【讨论】:

    • 我测试了这个实现,我发现这比调用 dao.findB(aId) 12,000 次慢 5 倍。应用服务器和数据库都位于同一台机器上,使用本地数据库时调用数据库的次数没有太大区别。我最终回去并使用了 dao.findB(aId)。就我而言,数据库始终是本地的。
    猜你喜欢
    • 2022-01-24
    • 1970-01-01
    • 2013-11-20
    • 2021-10-18
    • 2015-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    相关资源
    最近更新 更多