我正在开发一个使用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表示:
如果实体实例包含在持久性上下文中,则从那里返回。
这意味着某种形式的缓存和/或延迟写入。createQuery和getResultList方法的javadoc没有这样说。
我不知道在此应用程序中有任何业务或技术要求会排除缓存,也不知道由于陈旧的实体或类似的原因而产生的任何问题。我将在可用时与项目团队的其他成员检查这些内容,但我只是想了解SO社区的意见,看看是否还有其他原因来构造和执行查询,而不是简单地使用find
(我见过这个:When use createQuery() and find() methods of EntityManager?。虽然它回答了问题re: createQuery和find之间的区别,但它没有在通过主键查找实体的上下文中回答它)
更新了附加信息
从原始DAO类中的其他方法来看,似乎已经有了一个有意/有意识的决定,不利用JPA托管对象。如前所述,按主键查找的方法使用JPQL查询。删除实体的方法还使用JPQL查询。更新实体的方法生成传递的实体对象的副本,并使用副本调用EntityManager#merge (因此,副本是托管对象,但从未使用或从该方法返回)
奇怪..。
发布于 2016-12-13 12:53:42
简短的回答,查找和选择查询没有区别。
您的问题表明您并不完全熟悉EntityManager和持久性上下文是什么。EntityManager实现不需要线程安全。如果EntityManager是由Spring或EJB容器注入的,那么它是线程安全的(因为它是线程本地代理),如果它是应用程序管理的(您通过调用EntityManagerFactory.createEntityManager()创建它,它不是线程安全的,您不能将它存储在一个变量中,但是每次都必须创建一个新的代理)。
持久化上下文是实体所在的位置,每当您创建一个新的EntityManager时,您都会得到一个新的持久性上下文(这条规则有例外)。当您持久化一个实体,或者从db加载一个现有实体(使用查找或查询)时,它将由持久性上下文管理。当您提交事务时,JPA会在持久性上下文管理的所有实体中运行,并检查该实体的状态,以确定应该向数据库发送哪些查询。
PersistenceContext可以看作是数据库顶部的第一级缓存。它的生命周期很短,通常不会超过交易时间。如果您对多个事务重复使用相同的entityManager,那么当加载更多数据时,大小可能会增加,这是不好的,因为每个事务都必须在持久性上下文中的所有实体中运行。
https://stackoverflow.com/questions/41120882
复制相似问题