JPA NamedQuery => where in collection?


T

The_S

Hi-Ho,

ich habe mal eine Frage ob und wie ich das mit JPA darstellen kann:

Klasse A hat eine Collection mit Klasse B. Objekte der Klasse B können in den B-Collections von mehreren A-Objekten auftauchen. Praktisch

Code:
// mapping
public class A {

  // mapping
  private Collection<B> bs;
}

...

// Pseudocode, wird natürlich automatisch gemapped
B b1 = new B();
B b2 = new B();
A a1 = new A();
A a2 = new A();
a1.add(b1);
a1.add(b2);
a2.add(b2);

Ich möchte jetzt einen Named-Query, der mir alle Objekte der Klasse A zurückgibt, deren B-Collection ein bestimmtes B-Objekt enthält. Also bpsw.:

Code:
entityManager.createNamedQuery(A.GET_A_WITH_B)
		.setParameter(1, b1)
		.getResultList();
// Rückgabe von a1

Nur wie sieht dazu der NamedQuery aus? Ich suche also in etwa sowas:

Code:
@NamedQuery(name=A.GET_A_WITH_B, query="SELECT a FROM A a WHERE 1? IN bs")

Ich hoffe ihr versteht was ich meine, ansonsten einfach nachfragen ;) .

Danke!

Ps.: Ich habe die selbe Frage hier schon gestellt, da konnte mir aber niemand helfen.
 
T

The_S

Das ist natürlich dumm. Kennst du/jemand irgendeinen brauchbaren Workaround? Oder muss ich wirklich auf NativeQuerys zurückgreifen?
 
T

The_S

Hm, das ist mir nicht so ganz klar (sorry, arbeite erst seit ein paar Tagen mit JPA) ... Wie könnte das denn aussehen? Ich könnte dann den NamedQuery ja erst erzeugen, wenn bereits ein Objekt von A instanziiert wurde :suspekt: .
 

Oliver Gierke

Erfahrenes Mitglied
Ein named query geht dann natürlich nicht mehr. Ein normaler JpaQuery hingegen schon:

Java:
StringBuilder builder = new StringBuilder("from User u where ");
for (String criteria : criterias) {
  builder.append("u.foo = ").append(criteria).append(" or ");
}
builder.delete(builder.lenght() - 4, builder.length());

Query query = em.query(builder.toString());
return query.getResultList();
Pseudocode... kompiliert so sicher nicht, aber die Idee sollte klar werden. Was auch möglich wäre, wär query-by-example zu benutzen. Dafür musst du allerdings auf die API deines Persistenceproviders zurück.

Wenn dich das Thema JPA DAOs mehr interessiert, hier ein kleines OpenSource Projekt, was von mir betreut wird: http://trac.synyx.org/hades

Gruß
Ollie
 
T

The_S

Naja, ich hätte halt gerne NamedQuerys gehabt ... darum gings ;) . Aber wenn das so nicht möglich ist, dann wirds wohl doch n normaler Query. Diese Umsetzung ist dann selbstredend kein Problem mehr, aber danke für den Code.

Dein OpenSource-Projekt sehe ich mir mal an - beruflich bin ich sowieso schon mittendrin. Aber ist schon ne verdammt geile Technik, muss man neidlos anerkennen ;-) .
 
T

The_S

Hab das jetzt mal versucht und mir noch mal durch den Kopf gehen lassen. Aber hab da wohl immer noch ein Verständnisproblem.

Ich hab in A ja eine Collection von Bs. Auf die Collection als Ganzes kann ich ja nicht über "IN" zugreifen. Aber wie kann ich alle Bs von A in einem Query über OR verknüpfen, wenn ich

1.) kein Objekt von A habe um die Bs auslesen zu können
2.) jedes A unterschiedlich viele Bs haben kann
3.) nur auf die Collection als ganzes zugreifen kann

Bzw. um es auf dein Beispiel von oben zu beziehen: Woher soll ich die "criterias" nehmen?

Danke und mit verwirrtem Gruß

The_S
 

gerritka

Mitglied
Sicher dass die in-Clause noch nicht mit 1.0 funktioniert?
Habe hier JPA mit Hibernate als Provider im Einsatz und da funktioniert das tadellos. Also z.B. where user.id = ?1 AND user.type in (?2)
Dabei ist ?2 dann vom Typ Collection, also z.B. eine List. Wichtig sind die Klammern um den Parameter.

Links:
http://edocs.bea.com/kodo/docs41/full/html/ejb3_langref.html#ejb3_langref_in

Wobei, wenn ich mir die Frage nochmal richtig durchles, es hier glaub ein Missverständnis wegen dem IN gab und was ganz anderes gewollt war ;)
 
Zuletzt bearbeitet: