0

I am working with legacy code. I have entity A and entity B class, but because entity B is being referenced many places, I try not to make changes on entity B. Followings are classes for these two entities. Entity B has a foreign key column which is primary key of the entity A and in the database table, the foreign key(aId) is associated with many primary keies of the table b(id).

What I need is a collection of A(id range between 1 - 10000 for example) that includes collection of B corresponding to aid when I make a query against table_a. Current implementation is get a collection of A(has large number of rows) first and then loop through each A in the collection then call dao.findB(aId) to set collection of B for the A. It causes many trips to the database. I try to minimize this trip. For example, if A has 50,000 rows, dao.findB(aId) will be called 50,000 times.

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;

 }
user3123690
  • 1,053
  • 5
  • 17
  • 27

2 Answers2

1

Something as below

Let say you have aid, by which you want to load the collection of 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();
Ankur Singhal
  • 26,012
  • 16
  • 82
  • 116
  • Thanks for your answer. I think that I didn't explain enough about my question. I just updated it. Could you take a look? – user3123690 Sep 03 '14 at 13:52
  • @user3123690 Even if you keep reference of `Entity B` inside `Entity A`, still same queries will be fetched. Alternative can be to query for `Entity B` based on `A id`. – Ankur Singhal Sep 03 '14 at 13:56
  • 'results' is a collection of B corresponding to aid. What I need is a collection of A(id range between 1 - 10000 for example) that included collection of B corresponding to aid. I don't think that I quite understand your response. – user3123690 Sep 03 '14 at 14:51
  • Sorry. I didn't how to ask the question. I updated my question. Hopefully it is clear now. – user3123690 Sep 03 '14 at 20:15
0

With the help of link How to define unidirectional OneToMany relationship in JPA and http://en.wikibooks.org/wiki/Java_Persistence/OneToMany, I got it work without making changes to the entity B. I did check SQL log and it saved excessive trip to the database.

When I query using following criteria, it returned a collection of the A that includes collection of B.

 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;

 }
Community
  • 1
  • 1
user3123690
  • 1,053
  • 5
  • 17
  • 27
  • I tested this implementation and I found out that this is 5 times slower than calling dao.findB(aId) 12,000 times. Both app server and database are located on the same machine and number of times calling database doesn't make much difference when use local database. I ended up went back and used dao.findB(aId). In my case, the database is always local. – user3123690 Sep 04 '14 at 22:20