【问题标题】:Return ResultSet with intact joins in Hibernate / JPA在 Hibernate / JPA 中返回具有完整连接的 ResultSet
【发布时间】:2020-09-04 15:45:49
【问题描述】:

我有 2 个实体:EntityA 和 EntityB。它们与一对多关系相关。

public class EntityA {

    @Identifier
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="ID", updatable = false, nullable = false)
    private long id;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name="ENTITY_A_ID", referencedColumnName="ID", nullable=true)
    private List<EntityB> entityBs;

   /* GETTERS SETTERS ... */
}
public class EntityB {

    @Identifier
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="ID", updatable = false, nullable = false)
    private long id;


    @Column(name="SOME_PROPERTY")
    private String someProperty;

    @ManyToOne
    @JoinColumn(name="ENTITY_A_ID")
    private EntityA entityA;
    /* GETTERS SETTERS ... */

}

我有一个查询,它将 EntityA 与 LEFT JOIN 连接到 Entity B。还有一个“ON”子句。 在正常的 SQL 术语中,这将是:

select * from EntityA eA left join EntityB eB
    on (eA.ID = eB.ENTITY_A_ID and eB.SOME_PROPERTY = "blabla" )
    where ...

所以我从加入的结果集中获得了急需的信息。我只希望记录与某些属性匹配时加入。如果 EntityB 与 join 子句匹配,我需要 EntityA、allways 和附加的 EntityB。

该项目是使用 Hibernate / JPA 设置的。我不知道如何检索所需的信息。此刻我有:

public class EntityADAO {

    public List<EntityA> findMethod() {

        CriteriaBuilder builder = entityManager.getCriteriaBuilder();

        CriteriaQuery<EntityA> query = builder.createQuery(EntityA.class);

        Root<EntityA> entityARoot = query.from(EntityA.class);
        Join<EntityA, EntityB> entityBJoin = entityARoot.join("entityB", JoinType.INNER);
        entityBJoin.on(new Predicate [] {builder.equal(entityBJoin.get("someProperty"), "fixed_val_for_now"});

       /* where clause left out for readability */

        TypedQuery<EntityA> q = entityManager.createQuery(query);

        return q.getResultList();

        }

    } 

所以我在这里.. 卡在我的 EntityAs 列表中。每当我在 EntityA 上调用 getEntityBs() 时,我都会得到所有这些.. 这是有道理的.. 但是我怎样才能检索加入的集合?

我坚持使用 JPA 和 Hibernate,因为这个选择不是我做的。

提前致谢!

【问题讨论】:

    标签: java hibernate jpa left-join jpa-criteria


    【解决方案1】:

    您需要的是自定义投影或 DTO。过滤实体集合可能会导致删除,因为实体始终反映当前 DBMS 状态并在事务结束时同步。

    您可以编写一个 JPQL 查询,就像 SQL 查询一样,满足您的需求。

    SELECT a.id, b.id 
    FROM EntityA a 
    LEFT JOIN EntityB b ON a.id = b.entityA.id AND b.someProperty = 'blabla'
    

    但这不会帮助您将结果具体化为丰富的对象。如果一个 Object[] 即元组对您的用例来说足够好,那么使用这种查询就可以了,但是如果您想映射到丰富的对象,我可以建议您看看Blaze-Persistence Entity-Views

    Blaze-Persitence 是基于 JPA 的查询构建器,它支持 JPA 模型之上的许多高级 DBMS 功能。我在它之上创建了实体视图,以允许在 JPA 模型和自定义接口定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您以您喜欢的方式定义您的目标结构,并通过 JPQL 表达式将属性(getter)映射到实体模型。由于属性名称用作默认映射,因此您通常不需要显式映射,因为 80% 的用例是拥有作为实体模型子集的 DTO。

    您的模型的映射可能如下所示简单

    @EntityView(EntityA.class)
    public interface EntityAView {
        long getId();
        @Mapping("entityBs[someProperty = 'blabla']")
        List<EntityBView> getEntityBs();
    }
    
    @EntityView(EntityB.class)
    public interface EntityBView {
        long getId();
    }
    

    查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

    EntityAView dto = entityViewManager.find(entityManager, EntityAView.class, id);

    Spring Data 集成让您可以像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

    【讨论】:

      猜你喜欢
      • 2023-04-07
      • 1970-01-01
      • 2015-05-27
      • 2023-04-07
      • 2018-08-01
      • 1970-01-01
      • 2017-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多