在使用EJB 3.1和JPA 2.0的系统中,应该在哪里缓存CriteriaQuery对象?

时间:2012-06-25 13:21:18

标签: jpa ejb-3.1

JPA 2.0规范在6.9节中提到CriteriaQuery个对象是可序列化的,因此可能比任何开放的EntityManagerEntityManagerFactory个实例更长:

  

CriteriaQuery对象必须是可序列化的。持久性供应商需要支持随后将CriteriaQuery对象反序列化为该供应商的runt-ime的单独JVM实例,其中两个运行时实例都可以访问任何所需的供应商实现类。

EJB 3.1规范在第21.2.2节中说明:

  

企业bean不得使用线程同步原语来同步多个实例的执行,除非它是具有bean管理的并发的Singleton会话bean。

如果我有一个无状态会话bean,希望使用从注入CriteriaQuery获得的CriteriaBuilder预先构建一堆@PersistenceContext个对象,我应该在哪里存储结果?< / p>

我可以想到以下几种可能性,但我担心除了一个以外的所有可能与上面的“无同步原语”条款相冲突:

  • Map中存储为我的一个bean实例字段的值,了解我必须同步对地图的访问。我的看法:第21.2.2条违规行为。

  • ConcurrentMap中存储为我的一个bean实例字段的值。我的看法:仍然违反21.2.2节,因为我确信ConcurrentMap实现在某处同步。

  • 在某个@Singleton EJB的实例字段中,@Singleton只存在于此类缓存中;使用bean管理的并发性这应该是合法的,但现在我想要使用这个CriteriaQuery缓存的所有无状态会话bean必须将单例注入其自身......似乎需要很多开销。

所以听起来严格来说,最后一个选项是唯一符合规范的选项。我是对的吗?

1 个答案:

答案 0 :(得分:1)

我会考虑将它们放在一个简单的静态环境中,可以从任何地方访问。问题在于初始化它们,因为您需要实体管理器实例来执行此操作。也许是用于初始化事物的单例ejb,如Call method in EJB on JBoss startup所述。单例可以初始化您的条件查询缓存,然后可以通过静态上下文为您的DAO提供条件查询。

另一种选择是使用内置支持预编译查询的JPQL。当然,你会失去使用条件API的一些优点,尽管我认为主要问题(类型安全等)可能没问题,因为如果预编译查询在部署时而不是运行时无效,则应抛出异常。