Criteria构建器joinSet提取Object而不是Set of Objects

时间:2016-03-26 20:53:52

标签: java jpa eclipselink criteria criteria-api

我有两个与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)

这意味着框架希望将类Table2的对象注入我的Table1Trimmed构造函数而不是Set of Table2对象。有没有办法使用条件构建器来实现这一目标?

2 个答案:

答案 0 :(得分:1)

最佳解决方案是创建仅包含特定字段的附加只读实体。

@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

答案 1 :(得分:0)

嗯,你要做的事情有两个问题。首先,您的查询会获得多行。您为tables2集合中的每个条目获取一行:

-----------------------------------------
|  TABLE1.ID  |  TABLE2.ID |  TABLE1_ID |
-------------+-------------+-------------
|     1      |     1       |     1      |
|     1      |     2       |     1      |
-----------------------------------------

如果您获取Table1,则可以,但如果您在JPQL或CriteriaQuery中构建,则不行。 Construct语句只能执行一行,一个类。如果您使Table1Trimmed具有Table2构造函数,则会看到每个Table2条目都会得到一个结果,而不是每个Table1条目的结果。

其次,JPA提供者可以使用Set的构造函数。可以从另一个Set构建HashSetCollection,但同样,Construct构造中没有任何内容可以构建Collection { {1}}。 (只是不得不说!:)。