首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我们如何在Hibernate (HBM)中表示一个懒惰的多对一关系,同时允许在急切模式中引用同一个类?

我们如何在Hibernate (HBM)中表示一个懒惰的多对一关系,同时允许在急切模式中引用同一个类?
EN

Stack Overflow用户
提问于 2019-10-17 17:59:46
回答 1查看 538关注 0票数 0

我正在努力使我的hibernate HBM文件中的多对一关系变得懒散。具体来说,我有一个DataElement类,它在多对一的关系中引用Filter元素,我希望在应用程序的其他部分保持对Filter的访问权限,使其变得懒散。

我尝试更改HBM文件,发现lazy="true“仅在类级别上可用。

DataElement的映射(我希望带有过滤器的多对一的映射是懒惰的)

代码语言:javascript
复制
<hibernate-mapping package="project.me" default-lazy="false" auto-import="false">
  <class name="DataElement" table="DATA_ELEMENT">
    <id name="id" type="java.lang.Long" column="ID"/>
    <many-to-one name="filter" class="project.me.Filter" column="FILTER_ID" cascade="all"/>
  </class>
</hibernate-mapping>

FilterAudit's映射(我希望具有过滤器的多对一映射是热切的)

代码语言:javascript
复制
<hibernate-mapping package="project.me" default-lazy="false" auto-import="false">
  <class name="FilterAudit" table="FILTER_AUDIT">
    <id name="id" type="java.lang.Long" column="ID"/>
    <many-to-one name="filter" class="project.me.Filter" column="FILTER_ID" cascade="all"/>
  </class>
</hibernate-mapping>

滤波器映射

代码语言:javascript
复制
<hibernate-mapping package="project.me" default-lazy="false" auto-import="false">
    <class name="Filter" table="FILTERS" lazy="true">
        <id name="id" type="java.lang.Long" column="M_ID"/>
        <property name="type" type="filterType" column="M_FILTER_TYPE"/>
        <many-to-one name="predicate" class="Predicate" column="PRED_ID" unique="true" not-null="true" cascade="all"/>
    </class>
</hibernate-mapping>

通过将lazy="true“放在Filter类的级别上,我懒洋洋地在应用程序中加载筛选器中的所有DTO,我不希望这样

是否有一种方法只为指定延迟加载-- DataElementFilter之间的关系--同时保持FilterAuditFilterE 228之间的加载渴望?

EN

回答 1

Stack Overflow用户

发布于 2019-10-18 03:06:50

我的建议:不要用急切的抓取。它会导致不一致,有时还会导致奇怪的查询。此外,当您使用急切抓取时,很难对性能进行优化。在上述情况下,我将创建不同的方法来使用一些fetch连接或实体图调用数据库。

我不使用HBM (或其他基于XML的映射)。我使用注释,为什么我不能为您提供XML (HBM似乎已经过时了。)的答案。

我喜欢的方法是使用JPA标准API而不是JPQL。有些人说JPQL更容易理解,但我更喜欢类型安全标准API,它不太容易出错。我更喜欢实体图,因为它们比获取联接更容易动态使用。尽管如此,其他选择也同样有效。

首先,我会设置适合的文章的实体类。(我推断为单向关系。)

代码语言:javascript
复制
@Entity
@Table(name = "DATA_ELEMENT")
public class DataElement {

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FILTER_ID")
    private Filter filter;

    //Constructors, getters and setters...

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof DataElement )) return false;
        return id != null && id.equals(((DataElement) o).getId());
    }

    @Override
    public int hashCode() {
        return 56;
    }
}

类似于FilterAudit (也是FetchType.LAZY).

然后是Filter (并不那么有趣,因为它是单向的)。

代码语言:javascript
复制
@Entity
@Table(name = "FILTERS")
public class Filter {

    @Id
    @GeneratedValue
    @Column(name = "M_ID")
    private Long id;

    // Other attributes omitted...

    //Constructors, getters and setters...

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Filter )) return false;
        return id != null && id.equals(((Filter) o).getId());
    }

    @Override
    public int hashCode() {
        return 14;
    }
}

现在,使用JPA标准API和实体图实现了用于初始化延迟负载(或不初始化)的相关部分。

代码语言:javascript
复制
public DataElement findByIdWithFilter(long id) {

    EntityGraph<DatElement> graph = entityManager.createEntityGraph(DataElement.class);
    graph.addAttributeNodes("filter");

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<DatElement> cq = cb.createQuery(DatElement.class);
    Root<DatElement> root = cq.from(DatElement.class);

    cq.where(cb.equal(root.get("id"), id));

    TypedQuery<DatElement> typedQuery = entityManager.createQuery(cq);
    typedQuery.setHint("javax.persistence.fetchgraph", graph);

    DatElement response = null;
    try {
        response = typedQuery.getSingleResult();
    }
    catch(NoResultException nre) {}

    return response;
}

要检索同一个类的对象,不需要它的关系,只需省略实体图。

代码语言:javascript
复制
public DataElement findByIdWithoutFilter(long id) {

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<DatElement> cq = cb.createQuery(DatElement.class);
    Root<DatElement> root = cq.from(DatElement.class);

    cq.where(cb.equal(root.get("id"), id));

    return entityManager.createQuery(cq).getSingleResult();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58438341

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档