Criteria builder joinSet 获取对象而不是对象集
Criteria builder joinSet fetches Object instead of Set of Objects
我有 2 个实体与 OneToMany 关系。
@Entity
public class Table1 implements Serializable {
@Id
private Long id;
private String field1;
private String field2;
private String field3;
@OneToMany
@JoinColumn(name = "table1_id")
private Set<Table2> tables2;
}
@Entity
public class Table2 {
@Id
private Long id;
private String field1;
}
我想使用条件生成器将数据从 Table1 提取到附加对象 Table1Trimmed
public class Table1Trimmed {
private Long id;
private Set<Table2> tables2;
public Table1Trimmed(Long id, Set<Table2> tables2) {
this.id = id;
this.tables2 = tables2;
}
}
我是这样做的
CriteriaQuery<Table1Trimmed> cq = criteriaBuilder.createQuery(Table1Trimmed.class);
Root<Table1> table1Root = cq.from(Table1.class);
SetJoin<Table1, Table2> tables2Join = table1Root.joinSet("tables2");
cq.select(criteriaBuilder.construct(Table1Trimmed.class, table1Root.get("id"), tables2Join));
List<Table1Trimmed> tables1Trimmed = em.createQuery(cq).getResultList();
但是当我 运行 我的应用程序时,我收到此错误
java.lang.NoSuchMethodException: Table1Trimmed.<init>(java.lang.Long, Table2)
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getConstructor(Class.java:1825)
at org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getConstructorFor(PrivilegedAccessHelper.java:172)
at org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl.populateAndSetConstructorSelection(CriteriaQueryImpl.java:400)
at org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl.select(CriteriaQueryImpl.java:93)
这意味着框架想要将 class Table2 的对象注入到我的 Table1Trimmed 构造函数中,而不是 Set of Table2 对象。有什么方法可以使用条件生成器实现此目的吗?
好吧,你在尝试做的事情上遇到了两个问题。首先是您的查询获得多行。 tables2
集中的每个条目都有一行:
-----------------------------------------
| TABLE1.ID | TABLE2.ID | TABLE1_ID |
-------------+-------------+-------------
| 1 | 1 | 1 |
| 1 | 2 | 1 |
-----------------------------------------
如果您提取到 Table1
,这没问题,但如果您在 JPQL 或 CriteriaQuery 中构建,则不行。一个Construct
语句只能做一行,一个class。如果您创建一个具有 Table2
构造函数的 Table1Trimmed
,您会看到每个 Table2
条目都会得到一个结果,而不是每个 Table1
条目都会得到一个结果。
其次,Set
没有 JPA 提供程序可以使用的构造函数。 Set
或 HashSet
可以从另一个 Collection
构造,但是,Construct
构造中没有任何东西可以构造 Collection
Table2s
。 (不得不这么说!:)。
最佳解决方案是创建仅包含特定字段的附加只读实体。
@ReadOnly
@Entity("table1trimmed")
@Table("table1")
public class Table1Trimmed {
@Id
private Long id;
@OneToOne
@JoinFetch(JoinFetchType.OUTER)
@JoinColumn(name = "table1_id")
private Set<Table2> tables2;
}
好的,我在这里找到了间接答案 [1]
[1]
2 JPA entities on the same table
我有 2 个实体与 OneToMany 关系。
@Entity
public class Table1 implements Serializable {
@Id
private Long id;
private String field1;
private String field2;
private String field3;
@OneToMany
@JoinColumn(name = "table1_id")
private Set<Table2> tables2;
}
@Entity
public class Table2 {
@Id
private Long id;
private String field1;
}
我想使用条件生成器将数据从 Table1 提取到附加对象 Table1Trimmed
public class Table1Trimmed {
private Long id;
private Set<Table2> tables2;
public Table1Trimmed(Long id, Set<Table2> tables2) {
this.id = id;
this.tables2 = tables2;
}
}
我是这样做的
CriteriaQuery<Table1Trimmed> cq = criteriaBuilder.createQuery(Table1Trimmed.class);
Root<Table1> table1Root = cq.from(Table1.class);
SetJoin<Table1, Table2> tables2Join = table1Root.joinSet("tables2");
cq.select(criteriaBuilder.construct(Table1Trimmed.class, table1Root.get("id"), tables2Join));
List<Table1Trimmed> tables1Trimmed = em.createQuery(cq).getResultList();
但是当我 运行 我的应用程序时,我收到此错误
java.lang.NoSuchMethodException: Table1Trimmed.<init>(java.lang.Long, Table2)
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getConstructor(Class.java:1825)
at org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getConstructorFor(PrivilegedAccessHelper.java:172)
at org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl.populateAndSetConstructorSelection(CriteriaQueryImpl.java:400)
at org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl.select(CriteriaQueryImpl.java:93)
这意味着框架想要将 class Table2 的对象注入到我的 Table1Trimmed 构造函数中,而不是 Set of Table2 对象。有什么方法可以使用条件生成器实现此目的吗?
好吧,你在尝试做的事情上遇到了两个问题。首先是您的查询获得多行。 tables2
集中的每个条目都有一行:
-----------------------------------------
| TABLE1.ID | TABLE2.ID | TABLE1_ID |
-------------+-------------+-------------
| 1 | 1 | 1 |
| 1 | 2 | 1 |
-----------------------------------------
如果您提取到 Table1
,这没问题,但如果您在 JPQL 或 CriteriaQuery 中构建,则不行。一个Construct
语句只能做一行,一个class。如果您创建一个具有 Table2
构造函数的 Table1Trimmed
,您会看到每个 Table2
条目都会得到一个结果,而不是每个 Table1
条目都会得到一个结果。
其次,Set
没有 JPA 提供程序可以使用的构造函数。 Set
或 HashSet
可以从另一个 Collection
构造,但是,Construct
构造中没有任何东西可以构造 Collection
Table2s
。 (不得不这么说!:)。
最佳解决方案是创建仅包含特定字段的附加只读实体。
@ReadOnly
@Entity("table1trimmed")
@Table("table1")
public class Table1Trimmed {
@Id
private Long id;
@OneToOne
@JoinFetch(JoinFetchType.OUTER)
@JoinColumn(name = "table1_id")
private Set<Table2> tables2;
}
好的,我在这里找到了间接答案 [1]
[1] 2 JPA entities on the same table