<强>是否有一种方法来改变所述JPA上一个单一的方法提取类型而不编辑实体对象吗

我具有由JPA实体类的共享ORM层。这个ORM层是由两个DAO层访问。一个DAO需要延迟加载,因为它是我的web应用程序,其他需要预先抓取,因为我需要它是线程安全的。

下面是一种示例性方法从我的线程DAO,

@PersistenceContext(unitName = "PersistenceUnit", type = PersistenceContextType.TRANSACTION)
private EntityManager em;

public ErrorCode findErrorCodeById(short id) {
    return (ErrorCode) em.createNamedQuery("ErrorCode.findById").
            setParameter("id", id).getSingleResult();
}

如何将使这个方法(或整个类)使用预先抓取?

有帮助吗?

解决方案

我假设你的实体关联(@OneToOne,@OneToMany,@ManyToOne)被fechted懒惰(FetchType.Lazy)

然后我能想到的两种方式:

一个。写两个JPA查询一个其中取懒惰的关联(这就是为休眠的默认方式),并且明确的力关联的急切装载(见“取”关键字查询)的第二查询。

        Query q = HibernateUtil.getSessionFactory().getCurrentSession()
                .createQuery("select c from Category as c" +
                        " left join fetch c.categorizedItems as ci" +
                        " join fetch ci.item as i");


B中。使用状态,Hibernate.initialize(实体)来强制一个实体的懒惰关系的急切装载在提取它(例如,通过取景器...)

ErrorCode lazyCode = findErrorCodeById(1);
// eager load associations
Hibernate.initialize(lazyCode);

其他提示

在JPA在每个持久性属性所指定的抓取模式,既可以通过注释或在XML映射文件。

因此,为了实现此目标的一个供应商JPA不可知的方式是为每个DAO层单独的映射文件。不幸的是,这将需要为每个映射文件单独PersistenceUnit,但你至少可以共享相同的实体类和相同JPQL查询。

代码框架遵循。

的persistence.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映射文件相反(你还是会想要两个持久性单元,虽然)。

可能比上述休眠溶液稍微更多的代码,但应用程序应移植到其他JPA供应商。

顺便说一句,OpenJPA中提供类似的功能,以休眠溶液上方使用FetchGroups(从JDO借用一个概念)。

最后一个警告,FetchType.LAZY是在JPA一个提示,如果需要的话提供者可以热切加载的行。

每个请求更新。

考虑这样的实体:

@Entity 
public class ErrorCode { 
    //  . . . 
    @OneToMany(fetch=FetchType.EAGER)  // default fetch is LAZY for Collections
    private Collection myCollection; 
    // . . .
}

在这种情况下,你仍旧需要两个持久性单元,但你只需要ORM-lazy.xml。我改变字段名称,以反映更真实的场景(仅集合和斑点使用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>

由于没有人提到OpenJPA的,我会在这里放一个答案。

在OpenJPA中,先前懒惰配置集合和字段可急切装载如下

    OpenJPAEntityManager kem = OpenJPAPersistence.cast(em);
    kem.getFetchPlan().addField(Order.class, "products");
    TypedQuery<Order> query = kem.createQuery(yourQuery, Order.class);

参考: HTTP: //openjpa.apache.org/builds/1.0.3/apache-openjpa-1.0.3/docs/manual/ref_guide_fetch.html

在JPA2 我使用 EntityGraphs ,它允许您定义要检索哪些相关实体:

https://docs.oracle.com/javaee/7 /tutorial/persistence-entitygraphs002.htm https://docs.oracle.com/javaee/7/tutorial/持久性entitygraphs003.htm

您创建一个NamedQuery像你一样,你附加一个提示与关键javax.persistence.loadgraphjavax.persistence.fetchgraph。这将检索您在图形中定义的相关实体。

您可以找到差异的“loadgraph”和“fetchgraph”这里的细节:什么是读取和加载实体之间的diffenece JPA的图表?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top