2016-03-26 16 views
0

Ich habe 2 Beziehungen mit Beziehung OneToMany.Kriterien Builder JoinSet Holt Objekt statt Set von Objekten

@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; 
} 

Ich möchte Daten von Tabelle 1 holen, um zusätzliche Objekt mit Kriterien Table1Trimmed Builder

public class Table1Trimmed { 

    private Long id; 
    private Set<Table2> tables2; 

    public Table1Trimmed(Long id, Set<Table2> tables2) { 
     this.id = id; 
     this.tables2 = tables2; 
    } 

} 

ich es tue, wie diese

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(); 

Aber wenn ich meine app leite ich erhalten Dieser Fehler

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) 

Es bedeutet, dass Framework Objekt der Klasse Table2 in meinem Table1Trimmed-Konstruktor statt Set von Table2-Objekten injizieren möchte. Gibt es eine Möglichkeit, dies mithilfe des Kriterienerstellers zu erreichen?

+0

Sie können kein Feld mit mehreren Werten in einer JPQL oder Criteria Abfrage auswählen (und das ist effektiv, was Sie tun, indem Sie das Konstrukt verwenden). Siehe die JPA-Spezifikation JPQL "BNF" Notation –

Antwort

1

Die beste Lösung besteht darin, eine zusätzliche schreibgeschützte Entität zu erstellen, die nur bestimmte Felder enthält.

@ReadOnly 
@Entity("table1trimmed") 
@Table("table1") 
public class Table1Trimmed { 

    @Id 
    private Long id; 
    @OneToOne 
    @JoinFetch(JoinFetchType.OUTER) 
    @JoinColumn(name = "table1_id") 
    private Set<Table2> tables2; 

} 

Ok ich habe eine indirekte Antwort hier [1]

[1] 2 JPA entities on the same table

0

Nun, Sie haben zwei Probleme mit dem, was Sie versuchen zu tun. Zuerst erhalten Sie mehrere Zeilen mit Ihrer Abfrage. Sie erhalten eine Zeile für jeden Eintrag in der tables2 Satz:

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

Welche OK ist, wenn Ihr in Table1 holen, aber nicht in Ordnung, wenn Ihr innerhalb JPQL oder CriteriaQuery zu konstruieren. Eine Construct Anweisung kann nur eine Zeile, eine Klasse ausführen. Wenn Sie einen Table1Trimmed erstellen, der einen Table2-Konstruktor hat, sehen Sie, dass Sie ein Ergebnis für jeden Table2-Eintrag anstelle eines Ergebnisses für jeden Table1-Eintrag erhalten.

Zweitens gibt es keinen Konstruktor für Set, den ein JPA-Provider verwenden kann. Eine Set oder HashSet kann aus einer anderen Collection konstruiert werden, aber wiederum gibt es in der Construct Konstruktion, die eine Collection von Table2s konstruieren kann, nichts. (Musste nur sagen! :).

+0

Verstanden, aber wissen Sie, wie zu erreichen, was ich versuche zu tun, mit Criteria Builder? –

+0

Und ich meine in hübscher Weise, weil ich einige manuelle Objektgruppierung etc. weglassen möchte. –

+0

Ja, eine kleinere, ReadOnly Entity zu erstellen macht Sinn –