2016-09-13 12 views
1

を選択することはできませんリストまたは設定します。は、私はHQLを使用して新しいオブジェクトを作成したいので、私は次のクエリを発行しようとした容器

org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [com.pizzaboy.dto.OrderDTO]. Expected arguments are: com.pizzaboy.pojo.Adress, java.util.Date, com.pizzaboy.pojo.DeliveryType, com.pizzaboy.pojo.Restaurant, com.pizzaboy.pojo.Dish [SELECT new com.pizzaboy.dto.OrderDTO(o.adress, o.orderDate, dt, r, elements(d)) FROM com.pizzaboy.pojo.Order o JOIN o.user u JOIN FETCH o.deliveryType dt JOIN FETCH o.restaurant r JOIN FETCH o.dishes d WHERE u.id=:id] 

はしかし、それは確かに、設定されている:

@Entity 
@Table(name = "orders", catalog = "PIZZABOY") 
public class Order implements java.io.Serializable { 

private Integer id; 
private Adress adress; 
private DeliveryType deliveryType; 
private Payment payment; 
private Restaurant restaurant; 
private User user; 
private Date orderDate; 
private Set<Dish> dishes = new HashSet<Dish>(0); 

... 
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL) 
public Set<Dish> getDishes() { 
    return this.dishes; 
} 

public void setDishes(Set<Dish> dishes) { 
    this.dishes = dishes; 
} 

なぜ私はこのエラーを取得し、それを修正する方法?

PS OderDTOコンストラクタ

public OrderDTO(Adress adress, Date orderDate, DeliveryType deliveryType, Restaurant restaurant, 
      List<Dish> dishes) { 
+0

をしてください適用されません。 OrderDTOコンストラクタを投稿する –

+0

@JoeTaras question updated – 0x6B6F77616C74

+0

わかりやすくするために、両方のオブジェクトでSet(またはList)を使用できますか?現在、SetをフェッチしてListとして使用しようとしています。 –

答えて

1

あなたは、コレクションをこのように戻すことはできません:あなたはHQL/JPQLを実行すると、結果がオブジェクト - ここであなたは、オブジェクトとリレーショナルの世界の間でレルム間の内部にありますテーブル指向の空間で計算が行われます。

なぜ簡単にしないのですか?

String hql = "SELECT new com.pizzaboy.dto.OrderDTO(o)" 
    + " FROM Order o JOIN o.user u " 
    + " JOIN FETCH o.deliveryType dt" 
    + " JOIN FETCH o.restaurant r " 
    + " JOIN FETCH o.dishes d" 
    + " WHERE u.id=:id"; 

public OrderDTO(Order order) 
{ 
    this.adress = order.getAddress(); 
    this.deliveryType = order.getDeliveryType(); 
    this.restaurant = order.getRestaurant(); 
    this.dishes = new ArrayList<>(order.getDishes()); 
} 

あなたがFETCHを指定したので、Hiberanteが、これは希望、ORMとしての仕事をするために世話をするエンティティの関連するエンティティ/コレクションをロードし、正しい場所(に入れますおそらくは1つのSQLクエリで発生します)。

熱心にインラインFETCHを使用してコレクションをロードすることはできませんようで、その理由は、あなたがfecthの複数bagsに参加できないという事実に似た技術的な制限(多分それはバグと考えるべきであるが、そこだということです単一のクエリ)。

ので、あなたは2つの選択肢が残されています。

  1. クエリからFETCHを削除して、手動で怠惰なプロパティの初期化:これは公開されます

    SELECT new com.pizzaboy.dto.OrderDTO(o) 
    FROM Order o 
        JOIN o.user u 
    WHERE u.id=:id 
    

    public OrderDTO(Order order) 
    { 
        Hibernate.initialize(order.getAddress()); 
        this.adress = order.getAddress(); 
    
        Hibernate.initialize(order.getDeliveryType()); 
        this.deliveryType = order.getDeliveryType(); 
    
        Hibernate.initialize(order.getRestaurant()); 
        this.restaurant = order.getRestaurant(); 
    
        Hibernate.initialize(order.getDishes()); 
        this.dishes = new ArrayList<>(order.getDishes()); 
    } 
    

    をあなたはN + 1問題にあなたを避けることができます:batch-fetch

  2. エンティティグラフ/フェッチ・プロファイルを使用します。インラインフェッチ結合を使用して、私はカスタムオブジェクトの選択とエンティティグラフを使ったことがないので

    SELECT new com.pizzaboy.dto.OrderDTO(o) 
    FROM Order o 
        JOIN o.user u 
    WHERE u.id=:id 
    
    EntityGraph<Order> graph = entityManager.createEntityGraph(Order.class); 
    graph.addAttributeNodes(Order_.deliveryType, Order_.restaurant); 
    graph.addSubgraph(Order_.dishes); 
    
    entityManager.createQuery(hql) 
        .setHint("javax.persistence.fetchgraph", graph) 
        .setParameter("id", userId) 
        .getResultList(); 
    

    を、これは同じバグを打つことができ

DTO これは、とほぼ同じものと同じです::ちょうどentiを返しますあなた自身(おそらくあなたはDETACHED州でそれを望みます)。
あなたが異なるエンティティおよび/またはエンティティのプロパティおよび/または数、合計、+ bの、のような機能的な計算の構成されているものを処理するために持っているとき明らかに、これは、...

+0

それは私に例外を与えます: "クエリ指定の結合フェッチが、フェッチされた関連の所有者が選択リストに存在しませんでした。 – 0x6B6F77616C74

+0

"しかし、私は関連するEntityとほとんど同じことであるDTOを返すのにあまり使われていません。単にエンティティ自体を返してください"。私は私の問題の簡略版を示した。 DTOがさまざまなオブジェクトの構成要素である場合はどうなりますか? – 0x6B6F77616C74

+0

ください、更新を参照してください –

関連する問題