2

Let's say I have two entities:

@Entity
public class Customer implements Serializable {
    ...
    @OneToMany(cascade=ALL, mappedBy="customer")
    public Set<Order> getOrders() { 
        return orders; 
    }
    ...
}

@Entity
public class Order implements Serializable {
    ...
    @ManyToOne
    @JoinColumn(name="CUST_ID", nullable=false)
    public Customer getCustomer() { 
        return customer; 
    }
    ...
}

Then, I'm persisting Customer entity, and after that, Order entity with reference to previously added Customer. When I retrieve this customer from database, and call getOrders, it returns empty set. Is it normal behaviour? If it is, what can I do to automatically refresh this set when I add new Order entity?

user1315305
  • 1,329
  • 2
  • 11
  • 20

2 Answers2

7

Jpa does not maintain relationships for you, the application is required to set both sides of bidirectional relationships to keep them in synch with the database. Add order to the orders list when you set the order->customer relation and if customer is detached, merge it to have the changes to the collection picked up.

Otherwise you will need to explicitely refresh using em.refresh or a query with a refresh query hint after the transaction, or evict the customer from the caches. Either way, it requires a database hit that is easily avoided by just maintaining both sides of relationships.

Chris
  • 20,138
  • 2
  • 29
  • 43
  • I had this issue when trying to receive a OneToMany relationship from the entitymanager using em.find(...), but always received an empty list. I always keep the relationships up-to-date, but from the entitymanager I always receive an empty list, that I currently populate using em.refresh(...). Should I see a different behavior when using em.find(...)? – Ben Aug 03 '16 at 13:35
  • Ben you'll have to give more details as I don't see how you can call em.find() to get a OneToMany relationship. If the relationship doesn't have entries, either the database doesn't have them either, the cached Entity is stale (such as when you only add to one side of a bidirectional relationship, or updated the entity in different EntityManager after reading in from this one), or your mapping isn't correct. If em.refresh doesn't fix the issue, then it is likely either the database doesn't have what you think it does, or the mapping is incorrect. Try posting details in a question – Chris Aug 03 '16 at 13:54
  • Chris, I realize I was unclear. Sorry for that. Here is a new question regarding my issue: http://stackoverflow.com/questions/38760611/eclipselink-not-populating-lazy-onetoone-with-nested-lazy-onetomany-relation – Ben Aug 04 '16 at 07:08
2

If you retrieve the customer from the same transaction, then yes, it's expected behavior. The reason is that the EntityManager returns the order it has in its first-level cache, and that you created yourself, without adding any order to its set of orders. It's your responsibility to maintain the coherence of the object graph by maintaining the two sides of the association:

order.setCustomer(customer);
customer.addOrder(order);
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255