在 JPA 中,通过注释或 xml 映射文件在每个持久性属性上指定 Fetch 模式。
因此,实现目标的与 JPA 供应商无关的方法是为每个 DAO 层提供单独的映射文件。不幸的是,这将需要为每个映射文件使用单独的 PersistenceUnit,但您至少可以共享相同的实体类和相同的 JPQL 查询。
代码骨架紧随其后。
持久性.xml:
<persistence>
<persistence-unit name="dao-eager">
<mapping-file>orm-eager.xml</mapping-file>
</persistence-unit>
<persistence-unit name="dao-lazy">
<mapping-file>orm-lazy.xml</mapping-file>
</persistence-unit>
</persistence>
orm-eager.xml:
<entity-mappings>
<entity class="ErrorCode">
<attributes>
<basic name="name" fetch="EAGER"/>
</attributes>
</entity>
</entity-mappings>
orm-lazy.xml :
<entity-mappings>
<entity class="ErrorCode">
<attributes>
<basic name="name" fetch="LAZY"/>
</attributes>
</entity>
</entity-mappings>
然后只需在 DAO 层中为适当的持久性单元创建一个 EntityManagerFactory 即可。
实际上,您不需要两个映射文件,您可以在实体中指定 LAZY 或 EAGER 作为注释,然后在 xml 映射文件中指定相反的内容(尽管您仍然需要两个持久性单元)。
可能比上面的 Hibernate 解决方案多一点代码,但您的应用程序应该可以移植到其他 JPA 供应商。
顺便说一句,OpenJPA 使用 FetchGroups(从 JDO 借用的概念)提供了与上述 Hibernate 解决方案类似的功能。
最后一个警告,FetchType.LAZY 是 JPA 中的一个提示,如果需要,提供者可能会急切地加载行。
根据请求更新。
考虑这样的实体:
@Entity
public class ErrorCode {
// . . .
@OneToMany(fetch=FetchType.EAGER) // default fetch is LAZY for Collections
private Collection myCollection;
// . . .
}
在这种情况下,您仍然需要两个持久性单元,但您只需要 orm-lazy.xml。我更改了字段名称以反映更真实的场景(默认情况下,只有集合和 blob 使用 FetchType.LAZY)。因此生成的 orm-lazy.xml 可能如下所示:
<entity-mappings>
<entity class="ErrorCode">
<attributes>
<one-to-many name="myCollection" fetch="LAZY"/>
</attributes>
</entity>
</entity-mappings>
persistence.xml 看起来像这样:
<persistence>
<persistence-unit name="dao-eager">
<!--
. . .
-->
</persistence-unit>
<persistence-unit name="dao-lazy">
<!--
. . .
-->
<mapping-file>orm-lazy.xml</mapping-file>
</persistence-unit>
</persistence>