Java hibernate条件查询创建多个sql

Java hibernate条件查询创建多个sql,java,mysql,hibernate,spring-orm,Java,Mysql,Hibernate,Spring Orm,我在应用程序中遇到了一个关于hibernate标准的非常奇怪的问题。下面是我的源代码片段中提到的 实体类 import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.pe

我在应用程序中遇到了一个关于hibernate标准的非常奇怪的问题。下面是我的源代码片段中提到的

实体类

    import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "AIRPORT")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Airport implements Serializable {

    private static final long serialVersionUID = -7120581694566566178L;
    private Long id;
    private String countryCode;
    private String countryName;
    private String cityCode;
    private String cityName;
    private String airportCode;
    private String airportName;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", unique = true)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "COUNTRY_NAME")
    public String getCountryName() {
        return countryName;
    }

    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }

    @Column(name = "COUNTRY_CODE", length = 10)
    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    @Column(name = "CITY_CODE", length = 25)
    public String getCityCode() {
        return cityCode;
    }

    public void setCityCode(String cityCode) {
        this.cityCode = cityCode;
    }

    @Column(name = "CITY_NAME")
    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    @Column(name = "AIRPORT_CODE", unique = true, length = 10)
    public String getAirportCode() {
        return airportCode;
    }

    public void setAirportCode(String airportCode) {
        this.airportCode = airportCode;
    }

    @Column(name = "AIRPORT_NAME")
    public String getAirportName() {
        return airportName;
    }

    public void setAirportName(String airportName) {
        this.airportName = airportName;
    }
}
    Criteria criteria = getSession().createCriteria(getTemplateClass());
    criteria.addOrder(Order.asc("countryCode"));
    criteria.addOrder(Order.asc("cityCode"));
    criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
    criteria.setCacheable(true);
    return (List<Airport>) criteria.list();
DAO类

    import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "AIRPORT")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Airport implements Serializable {

    private static final long serialVersionUID = -7120581694566566178L;
    private Long id;
    private String countryCode;
    private String countryName;
    private String cityCode;
    private String cityName;
    private String airportCode;
    private String airportName;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", unique = true)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "COUNTRY_NAME")
    public String getCountryName() {
        return countryName;
    }

    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }

    @Column(name = "COUNTRY_CODE", length = 10)
    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    @Column(name = "CITY_CODE", length = 25)
    public String getCityCode() {
        return cityCode;
    }

    public void setCityCode(String cityCode) {
        this.cityCode = cityCode;
    }

    @Column(name = "CITY_NAME")
    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    @Column(name = "AIRPORT_CODE", unique = true, length = 10)
    public String getAirportCode() {
        return airportCode;
    }

    public void setAirportCode(String airportCode) {
        this.airportCode = airportCode;
    }

    @Column(name = "AIRPORT_NAME")
    public String getAirportName() {
        return airportName;
    }

    public void setAirportName(String airportName) {
        this.airportName = airportName;
    }
}
    Criteria criteria = getSession().createCriteria(getTemplateClass());
    criteria.addOrder(Order.asc("countryCode"));
    criteria.addOrder(Order.asc("cityCode"));
    criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
    criteria.setCacheable(true);
    return (List<Airport>) criteria.list();
如果我再次调用相同的代码,并假设我有1000个机场列表,那么它将在下面的查询中执行1000次。这种行为很奇怪。

Hibernate: select airport0_.ID as ID1_12_0_, airport0_.AIRPORT_CODE as AIRPORT_2_12_0_, airport0_.AIRPORT_NAME as AIRPORT_3_12_0_, airport0_.CITY_CODE as CITY_COD4_12_0_, airport0_.CITY_NAME as CITY_NAM5_12_0_, airport0_.COUNTRY_CODE as COUNTRY_6_12_0_, airport0_.COUNTRY_NAME as COUNTRY_7_12_0_ from AIRPORT airport0_ where airport0_.ID=?
Hibernate: select airport0_.ID as ID1_12_0_, airport0_.AIRPORT_CODE as AIRPORT_2_12_0_, airport0_.AIRPORT_NAME as AIRPORT_3_12_0_, airport0_.CITY_CODE as CITY_COD4_12_0_, airport0_.CITY_NAME as CITY_NAM5_12_0_, airport0_.COUNTRY_CODE as COUNTRY_6_12_0_, airport0_.COUNTRY_NAME as COUNTRY_7_12_0_ from AIRPORT airport0_ where airport0_.ID=?
Hibernate: select airport0_.ID as ID1_12_0_, airport0_.AIRPORT_CODE as AIRPORT_2_12_0_, airport0_.AIRPORT_NAME as AIRPORT_3_12_0_, airport0_.CITY_CODE as CITY_COD4_12_0_, airport0_.CITY_NAME as CITY_NAM5_12_0_, airport0_.COUNTRY_CODE as COUNTRY_6_12_0_, airport0_.COUNTRY_NAME as COUNTRY_7_12_0_ from AIRPORT airport0_ where airport0_.ID=?
........
........
甚至我也在使用ehcache,甚至我的标准中的下一行

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

任何帮助都将不胜感激。

我能想到发生这种情况的几个不同原因:

  • 您的实体中定义了一个关联,该关联在默认情况下配置为立即加入,并且您还指定该关联使用
    FetchMode。选择
    。(这称为N+1问题)

  • 当事务仍然打开时,您正在与设置为延迟加载的每个Airport对象的关联进行交互。通过交互,我的意思是,您正在使用getter访问关系,迫使Hibernate去代理关联的实体。由于解除代理是在事务仍然打开且关联实体尚未加载的情况下进行的,因此Hibernate会自动为您获取关联

  • 您已经编写了Airport实体的hashcode或equals方法,以便在事务中使用未急切加入的关联的属性,并强制hibernate解除代理,从而获取卸载的实体


  • 理性的猜测。让我困惑的是,从问题本身来看,似乎:1)N+1 fetch也在获取
    机场
    ,这意味着
    机场
    机场
    之间存在关联。2) 从生成的查询中,没有这种关联的提示:它不是~ToOne关系,因为第一个查询没有其他机场的字段。这似乎不是什么关系,因为额外的查询只是通过ID查询机场。我怀疑这是由其他原因造成的(可能是你的2或3),或者OP没有引用完整的信息SQL@Peter与任何其他实体均无任何关系。我已经添加了实体类供您参考。请尝试删除
    setCacheable(true)
    @JimmyT。这个解决方案起作用了,但我不理解为什么缓存在缓存结果时会创建这么多SQL。查询的缓存项只包含对象的ID。如果在缓存中找到查询,Hibernate接下来将在缓存中查找对象。如果查询结果在缓存中,但对象不在缓存中,则Hibernate将通过对象ID从数据库加载对象。