繁体   English   中英

JPA EntityManager:“查找”与“ createQuery”和“ getResultList”

[英]JPA EntityManager: 'find' vs. 'createQuery' and 'getResultList'

我正在使用JPA(不是JPA-2)的旧代码库,并且在DAO实现类中遇到了以下方法,以按ID(也是主键)检索单个实体:

public EmailTemplate findEmailTemplateById(long id) {

    LOG.debug("Entering findEmailTemplateById(id='" + id + "')");
    // Construct JPQL query       
    String queryString = "SELECT a FROM EmailTemplate a " +
            "WHERE templateId = :templateId";
    Query query = entityManager.createQuery(queryString);

    query.setParameter("templateId", id);

    LOG.debug("Using query " + queryString);

    List<EmailTemplate> resultList = query.getResultList();

    LOG.debug("Exiting findEmailTemplateByName(id='" + id + "') results size " + resultList.size() + " ( returns null if 0 )");

    if (resultList.isEmpty() || resultList.size() == 0) {
        return null;
    } else {
        return resultList.get(0);
    }

}

现在,我需要为不同的实体编写类似的DAO类,并且通过主键查找实体的方法看起来要简单得多!

@Override
public EmailTemplateEdit findEmailTemplateEditById(long id) {
    LOG.debug("Entering findEmailTemplateEditById(id={})", id);
    return entityManager.find(EmailTemplateEdit.class, id);
}

原始作者没有来问这个问题,所以我想知道是否有人可以提出他为何构造JPQL查询而不是简单地使用EntityManager#find(Class<T> entityClass, Object primaryKey)

find方法的Javadoc说:

如果实体实例包含在持久性上下文中,则从那里返回它。

这表明某种形式的缓存和/或延迟的写入。 createQuerygetResultList方法的Javadoc不会这样说。

我没有意识到此应用程序中的任何业务或技术要求都将阻止缓存,也没有意识到由陈旧的实体或类似实体导致的任何问题。 我将与项目团队的其他成员一起检查这些情况,但是我只是想以SO社区的意见为依据,查看是否还有其他原因构造和执行查询而不是简单地使用find来构建和执行查询。

(我已经看到了这一点: 当使用EntityManager的createQuery()和find()方法时吗?虽然它回答了以下问题:createQuery和find之间的区别,但是在通过主键查找实体的上下文中它没有回答)

更新了其他信息

通过查看原始DAO类中的其他方法,似乎已经有一个故意/有意识的决定,不利用JPA管理的对象。 如上所述,按主键查找的方法使用JPQL查询。 删除实体的方法还使用JPQL查询。 更新实体的方法将复制传入的实体对象,并使用该副本调用EntityManager#merge (因此,该副本是托管对象,但从不使用该方法或从该方法返回)
奇怪的 ....

简短的答案,查找和选择查询没有区别。

您的问题表明您并不完全了解EntityManager和Persistence上下文。 EntityManager实现不需要是线程安全的。 如果EntityManager是由Spring或EJB容器注入的,则它是线程安全的(因为它是线程本地代理),如果它是应用程序管理的(通过调用EntityManagerFactory.createEntityManager()创建的,则不是线程安全的),并且您不能将其存储在变量中,而每次都必须创建一个新变量。

持久性上下文是实体所在的位置,每当您创建新的EntityManager时,您都会获得一个新的持久性上下文(此规则有例外)。 当您持久化一个实体,或从数据库(使用查找或查询)加载现有实体时,它将由持久性上下文管理。 提交事务时,JPA会在Persistence上下文管理的所有实体中运行,并检查实体的状态以找出应将哪些查询发送到数据库。

PersistenceContext可以看作是数据库顶部的一级缓存。 这意味着使用寿命很短,通常不超过交易时间。 如果您将同一entityManager用于多个事务,则大小可能会随着加载更多数据而增长,这很糟糕,因为每个事务都必须在持久性上下文中遍历所有实体。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM