2016-10-13 1 views
0

Angenommen, wir haben die folgende Situation: Ein Elternteil hat eine Liste von Kindern, während jedes Kind entweder vom Typ "Nummer" oder "Alphabet" ist und ich möchte die Eltern entwederJPA @NamedQuery Wählen Sie durch @OneToMany Objekttyp

auswählen
  • eine oder mehrere „Nummer“ Kinder, deren „Nummer“ ist gleich 42
  • haben keine „Nummer“ Kinder überhaupt (kann aber auch „Alphabet“ Kinder haben)

ich habe die folgendes minimales Beispiel und ich habe den ersten Fall schon gelöst aber keine Ahnung über den zweiten o ne, weil ich annehme, dass ich nach Objekttyp filtern müsste und mir nicht sicher ist, ob dies machbar ist oder nicht nur über SQL (ich möchte nicht in Java filtern, um die Anzahl der betroffenen Entitäten so früh wie möglich zu reduzieren).

Parent.java

import java.io.Serializable; 
import java.util.List; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.NamedQueries; 
import javax.persistence.NamedQuery; 
import javax.persistence.OneToMany; 

@Entity 
@NamedQueries({ 
    @NamedQuery(name = "findWithNumberChildrenContainingNumber42", query = "SELECT nc.parent from NumberChild nc WHERE nc.number = 42"), 
    @NamedQuery(name = "findWithoutNumberChildren", query = "?") 
}) 
public class Parent implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @OneToMany(mappedBy = "parent") 
    private List<Child> children; 

    // ... 
} 

Child.java

import java.io.Serializable; 
import javax.persistence.ManyToOne; 
import javax.persistence.MappedSuperclass; 

@MappedSuperclass 
abstract class Child implements Serializable { 

    @ManyToOne 
    private Parent parent; 

    // ... 
} 

NumberChild.java

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 

@Entity 
public class NumberChild extends Child { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    private Integer number; 

    // ... 
} 

AlphabetChild.java

import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 

@Entity 
public class AlphabetChild extends Child { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    private String alphabet; 

    // ... 
} 
+1

Normalerweise befasse ich mich nur mit nativen Abfragen, aber dies funktioniert nicht in JPQL 'SELECT p FROM Übergeordnetes p WHERE p.id NICHT IN (SELECT nc.parent.id von NumberChild nc)'. – coladict

+0

@coladict Wenn Sie dies als eine "Antwort" umschreiben, würde ich es akzeptieren! – Smutje

+0

Nun, es ist vielleicht keine gute Antwort, denn zumindest in Hibernate optimiert die Unterabfrage nicht 'select parent_id from number_child', sondern verbindet sie tatsächlich mit der NumberChild-Tabelle mit Parent nach dieser ID und wählt sie aus der Parent-Tabelle aus . Die real erzeugte Anfrage ist unnötig ineffizient. – coladict

Antwort

1

Es stellte sich heraus, dass die vorherige Abfrage komplizierter war als nötig, also hier ist eine, die ich gerade getestet habe.

SELECT p FROM Parent p WHERE p NOT IN (SELECT nc.parent FROM NumberChild nc) 

Nun, die Namen in meinem Test waren anders, aber Hibernate Logs zeigen sie eine effizientere Abfrage generiert haben.

Verwandte Themen