使用entitymanager急切地加载集合

时间:2012-08-31 13:39:28

标签: java ejb entitymanager

我有一个实体(Contact),它有一个延迟加载的集合。我没有改变这个但是我需要在我执行em.find(Contact.class,myID)时加载集合,这可以在不更改实体且不使用带有fetch的jpql语句的情况下完成。 ?

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>();

}

来自我的无状态豆

@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());
}

2 个答案:

答案 0 :(得分:6)

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

缺点是这会向数据库发出两个查询:一个用于获取联系人,另一个用于获取TaskRelations。

另一个选择是创建一个Query,如下所示:

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();

此选项仅进行一次查询。

答案 1 :(得分:3)

你可以将@ arthuro的解决方案和反射结合起来调用所有的getter。像这样:

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;
}

然后像这样调用它:

Contact entity = findEager(em, Contact.class, mappedContact.getContact());