JPQL : mehrere join. Wie mein namedquery?
Hier ist eine schnelle Diagramm meiner Datenbank.
http://img17.imageshack.us/img17/2474/mpd.png
In diesem Schema, habe ich JPA-Entitäten (für alle Tabellen, die mit einem roten Quadrat).
Ich würde gerne eine JPQL-Abfrage, um alle Flugzeuge, die Verweise, Referenzen definiert, die von einem Referenz-Datentyp, gegeben durch den parameter.
Habe ich versucht :
SELECT DISTINCT a FROM Aircraft a JOIN FETCH a.references r WHERE EXISTS (SELECT ref FROM Reference ref WHERE ref = r AND ref.referenceType.id = :id)
Aber ich habe einen Fehler verursachen Eclipse mag nicht der alias in JOIN FETCH a.references *r*
und die Anfrage nicht im JUnit-test.
Hier meine Einheiten ohne getter/setter :
Flugzeug
@Entity
@Table(name = "T_R_AIRCRAFT_AIR", uniqueConstraints = @UniqueConstraint(columnNames = "AIR_NAME"))
public class Aircraft implements java.io.Serializable {
@Id
@Column(name = "AIR_ID", unique = true, nullable = false)
@TableGenerator(name="aircraftSeqStore",
table="T_S_APP_SEQ_STORE_AST",
pkColumnName="AST_SEQ_NAME",
valueColumnName = "AST_SEQ_VALUE",
pkColumnValue = "T_R_AIRCRAFT_AIR.AIR_ID",
allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE,
generator="aircraftSeqStore")
private Integer id;
@Column(name = "AIR_NAME", unique = true, nullable = false, length = 50)
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "T_J_REF_AIR_RFA",
joinColumns = { @JoinColumn(name = "RFA_AIR_ID", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "RFA_REF_ID", nullable = false, updatable = false) })
private Set<Reference> references = new HashSet<Reference>(0);
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "T_J_MAN_AIR_MNA",
joinColumns = { @JoinColumn(name = "MNA_AIR_ID", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "MNA_MAN_ID", nullable = false, updatable = false) })
private Set<Manual> manuals = new HashSet<Manual>(0);
@OneToMany(fetch = FetchType.LAZY,
mappedBy = "aircraft",
cascade = { CascadeType.REMOVE })
private Set<UserConfig> userConfigs = new HashSet<UserConfig>(0);
}
** Referenz **
@Entity
@Table(name = "T_E_REFERENCE_REF",
uniqueConstraints = @UniqueConstraint(columnNames = "REF_IDENTIFIER"))
public class Reference implements java.io.Serializable {
@Id
@Column(name = "REF_ID", unique = true, nullable = false)
@TableGenerator(name="referenceSeqStore",
table="T_S_APP_SEQ_STORE_AST",
pkColumnName="AST_SEQ_NAME",
valueColumnName = "AST_SEQ_VALUE",
pkColumnValue = "T_E_REFERENCE_REF.REF_ID",
allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE, generator="referenceSeqStore")
private Integer id;
@Column(name = "REF_IDENTIFIER", unique = true, nullable = false, length = 50)
private String identifier;
@Column(name = "REF_LINK")
private String link;
@Column(name = "REF_OBSERVATIONS", length = 4000)
private String observations;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REF_RFT_ID", nullable = false)
private ReferenceType referenceType;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REF_MAN_ID")
private Manual manual;
@OneToMany(fetch = FetchType.LAZY,
mappedBy = "reference",
cascade = { CascadeType.REMOVE })
private Set<Translation> translations = new HashSet<Translation>(0);
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "T_J_REF_AIR_RFA",
joinColumns = { @JoinColumn(name = "RFA_REF_ID", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "RFA_AIR_ID", nullable = false, updatable = false) })
private Set<Aircraft> aircrafts = new HashSet<Aircraft>(0);
}
** ReferenceType **
@Entity
@Table(name = "T_R_REFERENCE_TYPE_RFT",
uniqueConstraints = @UniqueConstraint(columnNames = "RFT_TYPE"))
public class ReferenceType implements java.io.Serializable {
@Id
@Column(name = "RFT_ID", unique = true, nullable = false)
@TableGenerator(name="referenceTypeSeqStore",
table="T_S_APP_SEQ_STORE_AST",
pkColumnName="AST_SEQ_NAME",
valueColumnName = "AST_SEQ_VALUE",
pkColumnValue = "T_R_REFERENCE_TYPE_RFT.RFT_ID",
allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE, generator="referenceTypeSeqStore")
private Integer id;
@Column(name = "RFT_TYPE", unique = true, nullable = false, length = 50)
private String type;
@OneToMany(fetch = FetchType.LAZY,
mappedBy = "referenceType",
cascade = { CascadeType.REMOVE })
private Set<Reference> references = new HashSet<Reference>(0);
@OneToMany(fetch = FetchType.LAZY,
mappedBy = "referenceType",
cascade = { CascadeType.REMOVE })
private Set<UserConfig> userConfigs = new HashSet<UserConfig>(0);
}
PS: ich vergaß zu sagen, dass eine Tabelle Hinzugefügt worden zwischen Flugzeug und Referenz. Dies ist das Handbuch, Tabelle. Aber ich glaube nicht, dass es einen Einfluss.
PS2: JPA-Implementierung von Hibernate.
Jede Idee, wie die mehreren beitreten ?
Danke !
InformationsquelleAutor MychaL | 2012-08-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie die Abfrage ausführen viel einfacher, wie folgt:
Habe ich
join fetch a.manuals
da sonst bekam ichLazyInitializationException
. HinzugefügtLEFT
um zu verhindern, dass das fehlen von Handbüchern, um Einfluss auf die Ausgabe.SELECT DISTINCT a FROM Aircraft a JOIN FETCH a.references JOIN FETCH a.references.referenceType WHERE a.references.referenceType.id = :id
? Vielen Dank für Ihre Geduld.Nein, diese Abfrage funktioniert nicht, da dieser Pfad
a.references.referenceType
ist nicht gültig. Denken Sie selbst: Sie verweisenreferenceType
Eigenschaft vonreferences
Sammlung, die letztere natürlich nicht haben.Ich verstehe, dass die Verwendung von join-fetch wurde getan, um die "Last" der Sammlungen, wurde für das lazy loading? So ist es möglich, erstellen Sie eine verschachtelte Abfrage? in SQL, wir hatten wohl die ersten, die es durch eine Abfrage auswählen, um alle Referenzen für ein ReferenceType-Id, dann einige Gelenke, um die Flugzeuge (über die join-Tabelle).
In JPQL sollten Sie vergessen Tabellen verknüpfen, da hier die Arbeit mit @Entitäten, @ElementCollections, @Embeddabbles und so weiter. In JPQL müssen Sie verbindet nur, wenn Sie wollen, erhalten Sie Zugriff auf Entität durch @ManyToMany oder @OneToMany Assoziation wie im aktuellen Fall. Ansonsten, wenn es @OneToOne oder @ManyToOne Assoziation von Flugzeugen mit Referenz, dann könnte man formulieren Sie Ihre Abfrage wie folgt:
SELECT DISTINCT a FROM Aircraft a LEFT JOIN FETCH a.manuals WHERE a.reference.referenceType.id = :id
Ok. Vielen Dank für diese Erklärungen. Also, wenn ich die Summe, die Verknüpfungen sind notwendig für alle
@ManyToMany
&@OneToMany
Verbände, aber nicht für@ManyToOne
&@OneToOne
....außer wenn es ein verzögertes laden, wo wir noch tun müssen, um eine join-fetch "laden", um unsere Einheit. Das ist genau ?InformationsquelleAutor Oleksandr Bondarenko