Java Hibernate,查询嵌套对象时忽略注释

Java Hibernate,查询嵌套对象时忽略注释,java,hibernate,jpa,entitymanager,hibernate-entitymanager,Java,Hibernate,Jpa,Entitymanager,Hibernate Entitymanager,我注意到我的模特有这种奇怪的行为。(这是我的模型): @实体(name=“A”) 公共A类{ @身份证 public String aId=UUID.randomUUID().toString(); @OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL) @JoinColumn(name=“aId”) 公共集b=新的HashSet(); } @实体(name=“B”) 公共B级{ @身份证 公共字符串bId=UUID.randomUUI

我注意到我的模特有这种奇怪的行为。(这是我的模型):

@实体(name=“A”)
公共A类{
@身份证
public String aId=UUID.randomUUID().toString();
@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
@JoinColumn(name=“aId”)
公共集b=新的HashSet();
}
@实体(name=“B”)
公共B级{
@身份证
公共字符串bId=UUID.randomUUID().toString();
公共援助;
@manytone(fetch=FetchType.EAGER)
@JoinColumn(name=“cId”)
@NotFound(action=NotFoundAction.IGNORE)
公共C obj;
}
@实体(name=“C”)
@其中(clause=“ran=‘hello’”)
公共C类{
@身份证
公共字符串cId=UUID.randomUUID().toString();
公共字符串ran=UUID.randomuid().toString();
公共LocalDateTime启动;
}
所以:类A有一个B的集合,它引用C

C有一个注释“Where”,其计算结果总是false

考虑这个测试用例:

    @Test
    public void test() throws IOException {

        Provider<EntityManager> provider = injector.getProvider(EntityManager.class);
        EntityManager em = provider.get();

        em.getTransaction().begin();

        A a = new A();
        B b = new B();
        b.aId = a.aId;
        a.b.add(b);
        C c = new C();
        b.obj = c;
        c.start = LocalDateTime.now().minusDays(10);
        em.persist(a);
        em.persist(b);
        em.persist(c);

        em.getTransaction().commit();

        em.clear();

        em.getTransaction().begin();

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<B> createQuery = cb.createQuery(B.class);
        Root<B> from = createQuery.from(B.class);
        CriteriaQuery<B> select = createQuery.select(from);


        List<B> resultList = em.createQuery(createQuery).getResultList();
        em.getTransaction().commit();

        resultList.forEach( b2 -> {
            Assert.assertNull(b2.obj); // This is correct
        });

        em.clear();

        em.getTransaction().begin();
        CriteriaBuilder cb2 = em.getCriteriaBuilder();
        CriteriaQuery<A> createQuery2 = cb2.createQuery(A.class);
        Root<A> from2 = createQuery2.from(A.class);
        createQuery2.select(from2);

        List<A> resultList2 = em.createQuery(createQuery2).getResultList();

        resultList2.forEach( a2 -> {
            a2.b.forEach( b2 -> {
                Assert.assertNull(b2.obj); // this should be null but is not
            });
        });

    }
@测试
public void test()引发IOException{
Provider Provider=injector.getProvider(EntityManager.class);
EntityManager em=provider.get();
em.getTransaction().begin();
A=新的A();
B=新的B();
b、 援助=援助;
a、 b.添加(b);
C=新的C();
b、 obj=c;
c、 start=LocalDateTime.now().minusDays(10);
em.a;
em.b;
em.c;
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
CriteriaBuilder cb=em.getCriteriaBuilder();
CriteriaQuery createQuery=cb.createQuery(B.class);
Root-from=createQuery.from(B.class);
CriteriaQuery select=createQuery.select(从);
List resultList=em.createQuery(createQuery).getResultList();
em.getTransaction().commit();
结果列表forEach(b2->{
Assert.assertNull(b2.obj);//这是正确的
});
em.clear();
em.getTransaction().begin();
CriteriaBuilder cb2=em.getCriteriaBuilder();
CriteriaQuery createQuery2=cb2.createQuery(A.class);
Root from2=createQuery2.from(A.class);
createQuery2.选择(from2);
List resultList2=em.createQuery(createQuery2.getResultList();
结果列表2.forEach(a2->{
a2.b.forEach(b2->{
Assert.assertNull(b2.obj);//这应该是null,但不是
});
});
}
因此,我正在做:

  • 添加所有模型:A、B和C以及属性集
测试1:

查询所有类型为B的对象。正确应用where子句,但未解析C

测试2:

查询A.B类型的所有对象已正确解析,但是引用B->C忽略where子句

这肯定是不对的?还是我遗漏了什么

编辑:


更多的测试表明,在BC关系中将抓取策略设置为LAZY可以解决这个问题(但是我不知道为什么)

您是否尝试将
@Where(clause=“ran='hello'”
移动到
B
C
之间的关系中:
public obj?这对我来说更直观,也更灵活。在任何情况下,都不要在映射上使用
EAGER
,因为使用此获取策略会有性能问题,以后很难删除。@Dherik这不起作用,因为ran是C的一个道具。B不知道它是否正在获取C,您不能引用C中的属性。(至少这对我不起作用). 这就是为什么我把注释放在实体本身上,因为取值确实考虑了注释(但是不是在多层取回,如在-> b->c中。让它考虑注释。我使用Apple,因为我遇到了EM关闭的问题。我有一个非常小的模型,最多有100个对象。性能不是一个大问题:
    @Test
    public void test() throws IOException {

        Provider<EntityManager> provider = injector.getProvider(EntityManager.class);
        EntityManager em = provider.get();

        em.getTransaction().begin();

        A a = new A();
        B b = new B();
        b.aId = a.aId;
        a.b.add(b);
        C c = new C();
        b.obj = c;
        c.start = LocalDateTime.now().minusDays(10);
        em.persist(a);
        em.persist(b);
        em.persist(c);

        em.getTransaction().commit();

        em.clear();

        em.getTransaction().begin();

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<B> createQuery = cb.createQuery(B.class);
        Root<B> from = createQuery.from(B.class);
        CriteriaQuery<B> select = createQuery.select(from);


        List<B> resultList = em.createQuery(createQuery).getResultList();
        em.getTransaction().commit();

        resultList.forEach( b2 -> {
            Assert.assertNull(b2.obj); // This is correct
        });

        em.clear();

        em.getTransaction().begin();
        CriteriaBuilder cb2 = em.getCriteriaBuilder();
        CriteriaQuery<A> createQuery2 = cb2.createQuery(A.class);
        Root<A> from2 = createQuery2.from(A.class);
        createQuery2.select(from2);

        List<A> resultList2 = em.createQuery(createQuery2).getResultList();

        resultList2.forEach( a2 -> {
            a2.b.forEach( b2 -> {
                Assert.assertNull(b2.obj); // this should be null but is not
            });
        });

    }