2017-01-18 7 views
0

私のアプリケーションで休止状態に関する非常に奇妙な問題に直面しています。以下は、私のソースコードから抜粋したものです。複数のSQLを作成するhibernate criteriaクエリ

エンティティークラス

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

DAOクラス

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=? 
........ 
........ 

でも私の基準では、以下の行も使用しています。

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

ご協力いただければ幸いです。

+1

「setCacheable(true)」 –

+0

@JimmyTを削除してみてください。このソリューションはうまくいきましたが、結果がキャッシュされると、キャッシュが非常に多くのSQLを作成している理由を理解できません。 –

+1

クエリのキャッシュエントリには、オブジェクトのIDのみが含まれます。クエリがキャッシュ内に見つかった場合、Hibernateは次にキャッシュ内のオブジェクトを探します。クエリ結果がキャッシュ内にあるが、オブジェクトが存在しない場合、HibernateはIDを介してデータベースからオブジェクトをロードします。合理的な推測。 –

答えて

0

私は、これはoccuringかもしれない理由をいくつかの異なった理由を考えることができます:

  1. あなたのエンティティが熱心に設定され、それに定義された関連付けは、デフォルトで参加しているし、その関連付けを使用するにも指定されていますFetchMode.SELECT。 (これはN + 1問題として知られています)

  2. トランザクションはまだ開いていますが、遅延ロードに設定されている各Airportオブジェクトの関連付けと対話しています。対話するということは、ゲッターを使ってリレーションにアクセスし、Hibernateに関連付けられたエンティティを非プロキシにすることです。トランザクションがまだ開いていて、関連エンティティがまだロードされていない状態でデプロキシが発生しているため、Hibernateは自動的に関連付けを取得します。

  3. あなたは空港エンティティのハッシュコードを書いたり、熱心に参加し、力がdeproxyため、トランザクション内ながら、無負荷のエンティティを取得するために休止状態にされていない関連のプロパティを使用する方法を等しくしています。

+0

。私に混乱させたのは、質問そのものから、1)N + 1フェッチでも「空港」がフェッチされているということです。これは、空港と空港の間の関係を意味します。 2)生成されたクエリから、そのような関連付けのヒントはありません。最初のクエリには別の空港のフィールドがないため、ToOne関係ではありません。余分なクエリはIDで空港に照会するだけなので、ToMany関係ではないようです。私はそれが何か他のもの(おそらくあなたの2か3かもしれない)によって引き起こされたと思われるか、OPは完全なSQLを引用していません。 –

+0

@Peter他のエンティティとの関係はありません。私はあなたの参照のためにエンティティクラスで追加しました。 –

関連する問題