简体   繁体   English

如何使用 LEFT JOIN 创建 JPA NamedQuery

[英]How to create JPA NamedQuery with LEFT JOIN

I have two entities: Car and Reservation.我有两个实体:汽车和预订。 I would like to create named query with LEFT JOIN.我想用 LEFT JOIN 创建命名查询。 I was trying to do this like it is described here How to create JPA query with LEFT OUTER JOIN but it doesn't work.我试图像这里描述的那样做这件事How to create JPA query with LEFT OUTER JOIN但它不起作用。 Do you have any idea what is wrong in my query?你知道我的查询有什么问题吗? I would like to show Cars which have NULL reservations.我想展示保留为 NULL 的汽车。 Anyway even with JOIN it does not work.无论如何,即使使用 JOIN 它也不起作用。 After starting application I have an error:启动应用程序后,我有一个错误:

Caused by: org.hibernate.HibernateException: Errors in named queries: Car.findAll
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:495) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    ... 22 common frames omitted

In principle I would like to achieve this query which in MySQL works原则上我想实现这个在 MySQL 中有效的查询

SELECT distinct * FROM car c LEFT JOIN reservation r ON c.id = r.car_id WHERE c.producer='producer' AND c.model='model' AND c.type='type' 
AND (r.date_of_rent < 'date1' AND r.date_of_return < 'date1') OR (r.date_of_rent > 'date2') OR r.date_of_rent IS NULL;

Car Entity汽车实体

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.NamedQuery;
import javax.persistence.OneToMany;

@Entity
@NamedQuery(name = "Car.findAll", query = "SELECT c FROM Car c LEFT JOIN c.reservation r WHERE c.producer=:producer "
        + "AND c.type=:type AND c.dailyPrice=:dailyPrice")
public class Car implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String producer;
    private String model;
    private int seatsNumber;
    private String type;
    private String registrationNumber;
    private double dailyPrice;
    private String description;
    @OneToMany(mappedBy = "car")
    private List<Reservation> reservations;

Reservation Entity预订实体

import java.io.Serializable;
import java.sql.Date;

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

@Entity
public class Reservation implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne
    private User user;
    @ManyToOne
    private Car car;
    private Date dateOfRent;
    private Date dateOfReturn;

Many thanks for help.非常感谢您的帮助。

UPDATE更新

Problem solved.问题解决了。 Query should look like this one查询应如下所示

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.NamedQuery;
import javax.persistence.OneToMany;

@Entity
@NamedQuery(name = "Car.findAll", query = "SELECT DISTINCT c FROM Car c LEFT JOIN c.reservations r WHERE "
        + "c.type=:type AND c.dailyPrice<=:dailyPrice AND ((r.dateOfRent < :dateOfRent AND r.dateOfReturn < :dateOfRent) OR "
        + "(r.dateOfRent > :dateOfReturn) OR (r.dateOfRent IS NULL))")
public class Car implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String producer;
    private String model;
    private Integer seatsNumber;
    private String type;
    private String registrationNumber;
    private Double dailyPrice;
    private String description;
    @OneToMany(mappedBy = "car")
    private List<Reservation> reservations;
SELECT c FROM Car c LEFT JOIN c.reservation r WHERE c.producer=:producer "
        + "AND c.type=:type AND c.dailyPrice=:dailyPrice

There is an error in this query c.reservation need to be changed to c.reservations .此查询有错误c.reservation需要更改为c.reservations

I would like to show Cars which have NULL reservations.我想展示保留为 NULL 的汽车。

You can't do it this way.你不能这样做。 Try to begin from this query:尝试从这个查询开始:

select c from Car c where not exists (
    select r.id from Reservation r where r.car.id = c.id
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM