Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use entitymanager to load collections eagerly

I have an entity (Contact) that has a collection that is lazy loaded. I do not which to change this but i need to load the collection when i do a em.find(Contact.class, myID) can this be done without changing the entity and without using jpql statement with fetch. ?

public class Contact implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id 
    @Column(name="contactId", nullable=false)
    public String contactId;    

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "contact", orphanRemoval = true, fetch=FetchType.LAZY)
    private List<ContactTaskRelation> taskRelations = new ArrayList<ContactTaskRelation>();

}

From my statless bean

@PersistenceContext(unitName="myContext")
private EntityManager em;

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private Contact getContact(ContactMapping mappedContact){
    //force em to load the collection of taskRelations
    return em.find(Contact .class, mappedContact.getContact());
}
like image 237
Marthin Avatar asked Aug 08 '26 21:08

Marthin


2 Answers

Contact entity = em.find(Contact.class, mappedContact.getContact());
entity.getTaskRelations().size(); // this will fetch the TaskRelations
return entity;

The downside is that this makes two queries to the database: one to get the Contact, and another one to fetch the TaskRelations.

Another option is to make a Query, like this:

String queryString = "SELECT model FORM Contact model JOIN FETCH model.taskRelations WHERE model.id = :id";
Query query = em.createQuery(queryString);
query.setParameter("id", mappedContact.getContact());
return query.getSingleResult(); // or getResultList();

This option makes only one query.

You can combine @arthuro's solution and reflection to invoke all getters. Something like this:

public static <T> T findEager(EntityManager em, Class<T> type, Object id) {
    T entity = em.find(type, id);
    for (Field field: type.getDeclaredFields()) {
        OneToMany annotation = field.getAnnotation(OneToMany.class);
        if (annotation != null) {
            if (annotation.fetch().equals(FetchType.LAZY)) {
                try {
                    new PropertyDescriptor(field.getName(), type).getReadMethod().invoke(entity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    return entity;
}

And then invoke it like this:

Contact entity = findEager(em, Contact.class, mappedContact.getContact());
like image 28
tibtof Avatar answered Aug 10 '26 10:08

tibtof



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!