0

我有 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 连接到实体 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 与连接子句匹配,我需要 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,因为这个选择不是我做出的。

提前致谢!

4

1 回答 1

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-意见

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

于 2020-05-19T14:28:33.490 回答