Hibernate Criteria API如何仅获取多对一关联实体的指定属性?
可行,以下是几种实现方式
方案1:使用JPA实体图(标准特性,兼容所有JPA实现)
JPA 2.1引入的实体图可以精确控制关联实体的抓取属性,完美匹配你的需求:
- 先在A类上定义实体图,指定要抓取的B的属性:
@Entity @NamedEntityGraph(name = "A.withBPartial", attributeNodes = { @NamedAttributeNode(value = "b", subgraph = "b.partialProps") }, subgraphs = { @NamedSubgraph(name = "b.partialProps", attributeNodes = { @NamedAttributeNode("id") // 需要其他属性的话,直接添加,比如@NamedAttributeNode("name") } ) } ) public class A { // 原有代码... }
- 在Criteria查询中应用这个实体图:
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<A> query = cb.createQuery(A.class); Root<A> root = query.from(A.class); // 执行查询时加载指定实体图 List<A> result = entityManager.createQuery(query) .setHint("javax.persistence.loadgraph", entityManager.getEntityGraph("A.withBPartial")) .getResultList();
生成的SQL只会查询A的所有属性,以及你指定的B的属性,返回的A实例里的B对象只会填充这些指定字段。
方案2:Hibernate专属扩展(直接简洁,依赖Hibernate)
如果你用Hibernate作为JPA实现,可以直接用它的Criteria扩展来指定抓取的属性:
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<A> query = cb.createQuery(A.class); Root<A> root = query.from(A.class); // 抓取关联的B,并指定只加载id属性 Fetch<A, B> bFetch = root.fetch(A_.b, JoinType.LEFT); ((org.hibernate.query.criteria.FetchParent<?, ?>) bFetch).fetch(B_.id); // 如果需要其他属性,继续调用fetch,比如.fetch(B_.name) List<A> result = entityManager.createQuery(query).getResultList();
这种写法更直接,不需要提前定义实体图,但只能在Hibernate环境下使用。
方案3:手动投影组装(通用但繁琐)
如果不想依赖特定实现或实体图,可以手动查询所需属性再组装对象:
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Tuple> query = cb.createTupleQuery(); Root<A> root = query.from(A.class); Join<A, B> bJoin = root.join(A_.b, JoinType.LEFT); // 选择A的所有属性和B的id(可添加其他B的属性) query.select(cb.tuple(root, bJoin.get(B_.id))); List<Tuple> tuples = entityManager.createQuery(query).getResultList(); // 手动把查询结果组装成A对象 List<A> result = tuples.stream().map(tuple -> { A a = tuple.get(0, A.class); B b = new B(); b.setId(tuple.get(1, Long.class)); // 有其他属性的话继续设置,比如b.setName(tuple.get(2, String.class)) a.setB(b); return a; }).collect(Collectors.toList());
这种方式兼容性最好,但需要手动处理对象组装,适合简单场景。
内容的提问来源于stack exchange,提问作者Work of Artiz
相关产品推荐
相关产品推荐

