JPA 2.0规范在6.9节中提到CriteriaQuery
个对象是可序列化的,因此可能比任何开放的EntityManager
或EntityManagerFactory
个实例更长:
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必须将单例注入其自身......似乎需要很多开销。
所以听起来严格来说,最后一个选项是唯一符合规范的选项。我是对的吗?
答案 0 :(得分:1)
我会考虑将它们放在一个简单的静态环境中,可以从任何地方访问。问题在于初始化它们,因为您需要实体管理器实例来执行此操作。也许是用于初始化事物的单例ejb,如Call method in EJB on JBoss startup所述。单例可以初始化您的条件查询缓存,然后可以通过静态上下文为您的DAO提供条件查询。
另一种选择是使用内置支持预编译查询的JPQL。当然,你会失去使用条件API的一些优点,尽管我认为主要问题(类型安全等)可能没问题,因为如果预编译查询在部署时而不是运行时无效,则应抛出异常。