2017-01-18 2 views
0

Я столкнулся с очень странной проблемой с критериями спящего режима в моем приложении. Ниже приведен фрагмент из моего исходного кода.запрос на спящий режим, создающий несколько sql

Объект класса

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(); 

Сгенерированный SQL при запуске приложения и запроса результат

Hibernate: select this_.ID as ID1_12_0_, this_.AIRPORT_CODE as AIRPORT_2_12_0_, this_.AIRPORT_NAME as AIRPORT_3_12_0_, this_.CITY_CODE as CITY_COD4_12_0_, this_.CITY_NAME as CITY_NAM5_12_0_, this_.COUNTRY_CODE as COUNTRY_6_12_0_, this_.COUNTRY_NAME as COUNTRY_7_12_0_ from AIRPORT this_ order by this_.COUNTRY_CODE asc, this_.CITY_CODE asc 

Если я снова назову тот же код и предположим, что у меня есть список аэропортов 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); 

Любая помощь была бы принята с благодарностью.

+1

Попробуйте удалить 'setCacheable (true)' –

+0

@JimmyT. Это решение сработало, но я не понимаю, почему кеш создает столько SQL, если результат кэшируется. –

+1

Кэш-запись для запроса содержит только идентификаторы объектов. Если запрос найден в кеше, Hibernate будет искать объекты в кеше. Если результат запроса находится в кеше, но объекты не являются, то Hibernate будет загружать объекты из базы данных через их идентификатор. –

ответ

0

Я могу думать о нескольких различных причин, почему это может быть происходящий:

  1. Ваше предприятие имеет объединение определено в нем, который настроен на нетерпеливый присоединиться по умолчанию, и вы также указано, что использование ассоциации FetchMode.SELECT. (Это называется проблемой N + 1)

  2. Пока транзакция по-прежнему открыта, вы взаимодействуете с ассоциацией каждого объекта аэропорта, который настроен на ленивую нагрузку. Посредством взаимодействия я имею в виду, что вы используете getter для доступа к отношению, заставляя Hibernate депроксировать связанный объект. Поскольку депроксирование происходит при открытой транзакции, а связанный объект еще не загружен, Hibernate автоматически получает связь для вас.

  3. Вы написали методы hashcode или equals вашего объекта в сущности, чтобы использовать свойство ассоциации, которое не с готовностью соединяется, и вынуждает спящий режим к deproxy и, таким образом, извлекать выгруженный объект, в то время как внутри транзакции.

+0

Рациональные догадки. Меня смутило то, что из самого вопроса кажется, что: 1) выборка N + 1 также выводит «аэропорт», что подразумевает, что ассоциация находится между «аэропортом» и «аэропортом». 2) Из сгенерированных запросов нет никаких намеков на такую ​​ассоциацию: это не отношение ToOne, потому что первый запрос не имеет полей для другого аэропорта. Кажется, это не отношение ToMany, потому что дополнительные запросы просто запрашивают аэропорт по ID. Я вроде подозреваю, что это вызвано чем-то другим (возможно, 2 или 3), или OP не цитирует полный SQL –

+0

@Peter. Нет никаких отношений с каким-либо другим объектом. Я добавил класс сущности для вашей справки. –

Смежные вопросы