不能 select 容器
Cannot select container
我想用 HQL 创建新对象,所以我尝试发出以下查询:
String hql = "SELECT new com.pizzaboy.dto.OrderDTO(o.adress, o.orderDate, dt, r, d)"
+ " FROM Order o JOIN o.user u "
+ " JOIN FETCH o.deliveryType dt"
+ " JOIN FETCH o.restaurant r "
+ " JOIN FETCH o.dishes d"
//+ " JOIN FETCH d.dishType disht "
+ " WHERE u.id=:id";
它给了我以下错误,就好像 "o.dishes" 不是 List 或 Set:
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]
不过,是Set,确实:
@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) {
您不能 return 以这种方式收集:当您执行 HQL/JPQL 时,您处于对象和关系世界之间的跨域中,结果是面向对象的,但是计算发生在面向 table 的 space.
上
为什么不让它变得简单?
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());
}
Hiberante 将负责作为 ORM 的工作,加载相关的 entities/collections 实体并将它们放在正确的位置(因为您指定了 FETCH
,这将可能 只发生一次 SQL 查询)。
似乎无法使用内联 FETCH
急切加载集合,原因是存在技术限制(也许它应该被认为是一个错误,类似于您无法加入的事实fecth 多个 bags
在单个查询中)。
所以你有两个选择:
从查询中删除 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
避免
使用实体图/获取配置文件:
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();
因为我从来没有使用自定义对象选择的实体图,这可能会遇到与使用内联连接提取相同的错误
但是,我认为 returning DTO
与相关的 Entity
几乎相同 没有多大用处: 只是 return 实体本身(可能你希望它处于 DETACHED
状态)。
显然,当您必须处理由不同实体组成的事物时,这并不适用 and/or 实体属性 and/or 函数计算,如计数、求和、a + b、...
我想用 HQL 创建新对象,所以我尝试发出以下查询:
String hql = "SELECT new com.pizzaboy.dto.OrderDTO(o.adress, o.orderDate, dt, r, d)"
+ " FROM Order o JOIN o.user u "
+ " JOIN FETCH o.deliveryType dt"
+ " JOIN FETCH o.restaurant r "
+ " JOIN FETCH o.dishes d"
//+ " JOIN FETCH d.dishType disht "
+ " WHERE u.id=:id";
它给了我以下错误,就好像 "o.dishes" 不是 List 或 Set:
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]
不过,是Set,确实:
@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) {
您不能 return 以这种方式收集:当您执行 HQL/JPQL 时,您处于对象和关系世界之间的跨域中,结果是面向对象的,但是计算发生在面向 table 的 space.
上为什么不让它变得简单?
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());
}
Hiberante 将负责作为 ORM 的工作,加载相关的 entities/collections 实体并将它们放在正确的位置(因为您指定了 FETCH
,这将可能 只发生一次 SQL 查询)。
似乎无法使用内联 FETCH
急切加载集合,原因是存在技术限制(也许它应该被认为是一个错误,类似于您无法加入的事实fecth 多个 bags
在单个查询中)。
所以你有两个选择:
从查询中删除
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
避免
使用实体图/获取配置文件:
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();
因为我从来没有使用自定义对象选择的实体图,这可能会遇到与使用内联连接提取相同的错误
但是,我认为 returning DTO
与相关的 Entity
几乎相同 没有多大用处: 只是 return 实体本身(可能你希望它处于 DETACHED
状态)。
显然,当您必须处理由不同实体组成的事物时,这并不适用 and/or 实体属性 and/or 函数计算,如计数、求和、a + b、...