我有两个实体Foo
和FooDerivedData
,如下所述。
实体Foo:
@Entity
@Table(name="FOO")
public class Foo {
// skipping property declarations
@OneToOne
@PrimaryKeyJoinColumn(name = "FOO_ID")
@Fetch(FetchMode.JOIN)
public getFooDerivedData() {
return fooDerivedData;
}
实体FooDerivedData
@Entity
@Table(name = "FOO_DERIVED_VW")
@Immutable
public class FooDerivedData {
@Id
@Column(name = "FOO_ID")
long fooId;
@Column(name = "FOO_COUNT")
private Integer fooCount;
@Column(name = "FOO_SUM")
private BigDecimal fooSum;
// Getters left out here
我正在使用JPA Criteria API(Hibernate是JPA实现),我需要在FooDerivedData
中加载Foo
的实例。默认情况下,这是急切获取的,但是我希望它使用内部联接,而不是FooDerivedData
的每个实例的单独select语句。我成功地能够针对FooDerivedData
添加内部联接。
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> root = criteriaQuery.from(Foo.class);
root.join("fooDerivedData");
Predicate p = getPredicate(); // details omitted here
criteriaQuery.select(root).where(p);
虽然我可以从日志中的SQL中看到为FOO_DERIVED_VW添加了内部联接,但是没有选择任何列。对于Foo
的每个实例,我仍然需要一个单独的select语句来获取我已经可用的数据。
目前查询是这样的:
select f.foo_id, f.foo_bar from from FOO f
inner join FOO_DERIVED_VW d on d.foo_id = f.foo_id;
select d.foo_id, d.foo_count, d.foo_sum from FOO_DERIVED_VW d where foo_id = ?;
select d.foo_id, d.foo_count, d.foo_sum from FOO_DERIVED_VW d where foo_id = ?;
请注意,我没有从已加入的FOO_DERIVED_VW中选择任何数据,并且此数据正在通过其他数据库命中来实现。我希望查询是这样的:
select f.foo_id, f.foo_bar, d.foo_count, d.foo_sum from from FOO f
inner join FOO_DERIVED_VW d on d.foo_id = f.foo_id;
如何在Criteria API中从已加入的实体中选择属性?我可以指示javax.persistence.criteria.Root来选择我加入的属性吗?
我尝试从连接更改为提取,或者我指定连接类型的提取。在任何一种情况下,它都失败了Hibernate QueryException。
Root<Foo> root = criteriaQuery.from(Foo.class);
root.fetch("fooDerivedData");
引起:org.hibernate.QueryException:查询指定的连接 获取,但获取的关联的所有者不存在 选择列表
答案 0 :(得分:1)
我认为你有几个选择。如果您的where条件不使用连接表中的任何列,那么您尝试的提取应该如下工作:
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> root = criteriaQuery.from(Foo.class);
root.fetch("fooDerivedData");
Predicate p = getPredicate(); // details omitted here
criteriaQuery.select(root).where(p);
如果你的谓词确实包含来自连接表的列,那么你可以像你一样加入(获取当前不会为此工作),然后通过添加它来指定动态实体图(从JPA 2.1开始)你有什么:
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder.createQuery(Foo.class);
Root<Foo> root = criteriaQuery.from(Foo.class);
root.join("fooDerivedData");
Predicate p = getPredicate(); // details omitted here
criteriaQuery.select(root).where(p);
EntityGraph<Foo> fetchGraph = entityManager.createEntityGraph(Foo.class);
fetchGraph.addSubgraph("fooDerivedData");
EntityManager.createQuery(criteriaQuery).setHint("javax.persistence.loadgraph", fetchGraph);
答案 1 :(得分:0)
我认为您不需要为FetchMode
指定getFooDerivedData()
,因为OneToOne关系的默认提取类型为EAGER
。希望这有帮助!