如何使用 HQL 从 2 个表中获取具有一对多关联的数据?

How can I fetch data from 2 tables using HQL having one to many association with each other?

我的数据库中有 2 个表,city 和 hotel_details。 city 的主键是 hotel_details 中的外键,并且与一对多关联相关联。我想通过从我的控制器调用 getAvailabilityStatus,基于 city_id 和 hotel_name 从 hotel_details 获取数据(状态、注册等)。以下是我的代码:

  1. 城市实体class
    @Entity
    @Table(name="city")
    public class City {

        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="id")
        private int id;
        
        @Column(name="city_name")
        private String cityName;
        
        @OneToMany(mappedBy="city",
                   cascade= {CascadeType.PERSIST, CascadeType.MERGE,
                             CascadeType.DETACH, CascadeType.REFRESH})
        private List<HotelDetails> hotelDetails;
        
        public City() {
            
        }
    
        public List<HotelDetails> getHotelDetails() {
            return hotelDetails;
        }
    
        public void setHotelDetails(List<HotelDetails> hotelDetails) {
            this.hotelDetails = hotelDetails;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getCityName() {
            return cityName;
        }
    
        public void setCityName(String cityName) {
            this.cityName = cityName;
        }
    
        @Override
        public String toString() {
            return "City [id=" + id + ", cityName=" + cityName + "]";
        }
}

2.HotelDetails实体class

       @Entity
        @Table(name="hotel_details")
        public class HotelDetails {
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="id")
        private int id;
        
        @ManyToOne(cascade= {CascadeType.PERSIST, CascadeType.MERGE,
                 CascadeType.DETACH, CascadeType.REFRESH})
        @JoinColumn(name="city_id")
        private City city;
        
        @Column(name="hotel_name")
        private String hotelName;
        
        @Column(name="available_date")
        @DateTimeFormat(pattern = "dd/MM/yyyy")
        private Date availableDate;
        
        @Column(name="price")
        private int price;
        
        @Column(name="gst")
        private int gst;
        
        @Column(name="status")
        private int status;
        
        @Column(name="room_type")
        private String roomType;
        
        
        public HotelDetails() {
        
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public City getCity() {
            return city;
        }
    
        public void setCity(City city) {
            this.city = city;
        }
    
        public String getHotelName() {
            return hotelName;
        }
    
        public void setHotelName(String hotelName) {
            this.hotelName = hotelName;
        }
    
    
        public Date getAvailableDate() {
            return availableDate;
        }
    
        public void setAvailableDate(Date availableDate) {
            this.availableDate = availableDate;
        }
    
        public int getPrice() {
            return price;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
    
        public int getGst() {
            return gst;
        }
    
        public void setGst(int gst) {
            this.gst = gst;
        }
    
        public int getStatus() {
            return status;
        }
    
        public void setStatus(int status) {
            this.status = status;
        }
    
        public String getRoomType() {
            return roomType;
        }
    
        public void setRoomType(String roomType) {
            this.roomType = roomType;
        }
    
        @Override
        public String toString() {
            return "HotelDetails [id=" + id + ", hotelName=" + hotelName + ", availableDate=" + availableDate + ", price="
                    + price + ", gst=" + gst + ", status=" + status + ", roomType=" + roomType + "]";
        }

}

3.HotelDAOImpl

@Component
@Repository
public class HotelDetailsDAOImpl implements HotelDetailsDAO {
    
    @Autowired
    private SessionFactory sessionFactory;

    @Override
    @Transactional
    public Set<String> getHotels() {
        Session currentSession = sessionFactory.getCurrentSession();
        Query theQuery2 = currentSession.createQuery("Select h.hotelName from HotelDetails h");
        List<String> listHotels = theQuery2.list();
        Set<String> hotels = new HashSet<String>(listHotels);
        return hotels;
    }
    
    @Override
    @Transactional
    public List<City> getAvailabilityStatus(int cityID, String hotelName,  String cityName) {
        Session currentSession = sessionFactory.getCurrentSession();
        Query theQuery4 = currentSession.createQuery("..."); 
        //theQuery4.setParameter("hotelName", hotelName); 
        //List<City> cities = theQuery4.list();
        return cities;
    
    }

}

String jpql = "select c from City c join c.hotelDetails h where h.hotelName = :hotelName";

String jpql = "select c from HotelDetails h join h.city c where h.hotelName = :hotelName";

然后

Query theQuery4 = currentSession.createQuery(jpql); 
theQuery4.setParameter("hotelName", hotelName); 
List<City> cities = theQuery4.list();

这只是一个示例,但是一旦您正确定义了连接和实体别名,您就可以按照自己喜欢的方式在 WHERE 子句中引用实体属性。

例如:

jpql += " AND c.id=:id AND h.price<:price AND h.availableDate BETWEEN :start AND :end";

与 select 子句相同,您可以使用以下所有组合:

"select c.cityName, h.status, ..." 
"select c, h from ..."

检查 many examples of how you can use JPQL/HQL 的 Hibernate ORM 查询。