【问题标题】:How can I fetch data from 2 tables using HQL having one to many association with each other?如何使用 HQL 从 2 个表中获取数据,它们之间存在一对多关联?
【发布时间】:2021-07-22 22:42:51
【问题描述】:

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

  1. 城市实体类
    @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实体类

       @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;
    
    }

}

【问题讨论】:

  • 您能否告诉我们您遇到了什么错误或您的尝试取得了多远?
  • 我可以从 city 表或 hotel_details 表中获取数据。因为我的实体类中为city id定义的数据类型是City,所以无法直接查询。如果我能找到一种方法来处理 HQL 中的类类型,也许这会有所帮助。如果 city id=? 我必须获取数据我试图找出如何在 HQL 查询中访问它。
  • 这应该插入到问题中,而不是作为评论发布

标签: spring spring-mvc spring-data-jpa hql


【解决方案1】:
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 查询。

【讨论】:

  • 出现错误:java.lang.ClassCastException:com.hms.myspringdemo.entity.City 类无法转换为 com.hms.myspringdemo.entity.HotelDetails 类(com.hms.myspringdemo.entity. City 和 com.hms.myspringdemo.entity.HotelDetails 位于加载程序的未命名模块 org.apache.catalina.loader.ParallelWebappClassLoader @23d1e5d0) com.hms.myspringdemo.dao.HotelDetailsDAOImpl.getAvailabilityStatus(HotelDetailsDAOImpl.java:60)
  • 我可以再次从 city 表或 hotel_details 表中获取数据。因为我的实体类中为city id定义的数据类型是City,所以无法直接查询。如果我能找到一种方法来处理 HQL 中的类类型,也许会有所帮助。
  • 在上面的 HQL 查询中,有没有什么方法可以为城市 id 或城市名称(以及酒店名称)添加 WHERE 子句?
  • 我已经更新了我的答案。您可以引用实体中映射的任何属性
猜你喜欢
  • 2012-05-20
  • 1970-01-01
  • 2014-06-21
  • 2016-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-13
相关资源
最近更新 更多