2016-10-13 2 views
0

次のような状況が想定されます。各子供が「数字」または「アルファベット」のいずれかのタイプである間に親に子供のリストがあり、両親を選択したい場合JPA @NamedQuery @OneToManyオブジェクトタイプで選択

  • 「数」42
  • に等しいまったく「数」子供を持っていない(ただし、「アルファベット」子供を有していてもよい)1つ以上の「数」の子ども

は私が持っているがあります最小限の例の後に、私はすでに最初のケースを解決しましたが、2番目のケースについては考えませんなぜなら、オブジェクト型でフィルターをかけなければならないと仮定しているからです。SQLを介して実行可能かどうかはわかりません(できるだけ早期に問題のエンティティの量を減らすためにJavaでフィルタリングしないでください)。

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

通常、私はネイティブクエリのみを扱いますが、これはJPQL 'SELECT p FROM Parent p WHERE p.id NOT IN(SELECT nc.parent.id from NumberChild nc)'では機能しません。 – coladict

+0

@coladictこれを「回答」として書き直すと、私はそれを受け入れます! – Smutje

+0

少なくともHibernateではサブクエリが 'number_childからparent_idを選択するように最適化されていませんが、実際にはそのIDでParentを持つNumberChildテーブルに結合し、それを親テーブルから選択するため、良い答えではないかもしれません。実際に生成されたクエリは、不必要に非効率的です。 – coladict

答えて

1

前のクエリは必要以上に複雑だったので、ここで私がテストしただけです。

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

私のテストでは、名前は異なっていましたが、Hibernateのログはより効率的なクエリを生成することを示しています。