1

I want to select an entity Person from the database (JPA with Hibernate). Person has has two (or more) oneToMany-Relationships, e.g. Address and Phone.

How would I fully restore the instance of Person and all related entities of Address and Phone. E.g. the focal Person has two Addresses and three Phones?

(I can persist the instance of Person with one command, but how can I load it?)

@Entity
public class Person implements Serializable { 
   @Id @GeneratedValue
   private int id;
   private String name;

   @OneToMany(mappedBy="person")
   private List<Address> addresses = new ArrayList<Address>();

   @OneToMany(mappedBy="person")
   private List<Phone> phones = new ArrayList<Phone>();        // plus getter and setter
}

@Entity
public class Address implements Serializable { 
    @Id @GeneratedValue
    private int id;

    @ManyToOne
    private Person person;
    private String onestring;         // plus getter and setter
}

@Entity
public class Phone implements Serializable { 
    @Id @GeneratedValue
    private int id;

    @ManyToOne
    private Person person;
    private String anotherstring;         // plus getter and setter
}

EDIT: I tried two ways suggested below. First try with calling getter:

@Stateless
public class PersonManager {

@PersistenceContext
private EntityManager em;

public Person getPerson(int id) {
   Person person = em.find(Person .class, id);
   person.getAddresses ();
   person.getPhones();
   return person;
}

Result: both lists are not initialized.

Second way:

@NamedQuery(name="PersonAddressesPhones", 
   query = "SELECT p FROM Person p " +
           "left join fetch p.addresses " +
           "left join fetch p.phones " +
           "WHERE p.id = :id")

Result: This causes the exception: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags

Marcus
  • 161
  • 1
  • 2
  • 12
  • This is a hibernate specific problem that shows up frequently. see http://stackoverflow.com/questions/17566304/multiple-fetches-with-eager-type-in-hibernate-with-jpa for details. – Chris Jun 23 '16 at 13:40
  • Unfortunately, for the second approach to work you have to deal with that hibernate issue (I did not see that coming). For the first to work, I think you need to define `@JoinColumn` annotations on your `@ManyToOne` mappings to denote ownership. Ref : http://stackoverflow.com/questions/11938253/jpa-joincolumn-vs-mappedby – Niks Jun 24 '16 at 05:33

1 Answers1

0

You can specify fetch = FetchType.EAGER in @OneToMany. This will fetch all phone, address entities related to Person when you do a find on a person id.

This is not a very good idea though. It's better to fetch data only when needed. Some of the alternatives are :

  1. Keep it as it is (be default, for @OneToMany, fetch type is lazy) and just call the getters to fill the collections on demand as and when needed (works as long as your session is not closed)

  2. You can write a (named) query which will fetch person with it's associated entities

Here's some good info about fetching strategies

Niks
  • 4,802
  • 4
  • 36
  • 55
  • 1
    I tried the first suggestion (call getter). But it seems that the connection is immediately closed (running on a wildfly server). I am working with the second suggestion already But this does not allow me to get both ArrayLists. Then hibernate throws an exception: `org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags` – Marcus Jun 23 '16 at 12:03
  • could you post the code for both in the original question? – Niks Jun 23 '16 at 14:35