2016-09-15 7 views
1

JPAのSpringへの実装をテストしているうちに、私のクエリが1回ではなく2回クエリを実行していることがわかりました。Hibernateがなぜ2回クエリを実行していますか?

@Data 
@Entity 
@Table(name = "superfan_star") 
public class Star implements Serializable 
{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(nullable = false) 
    private int id; 
    private String name; 
    private String nickname; 
    private String description; 
    private String thumbnail; 
    private String backgroundImage; 
    private Date created; 
    private Date updated; 

    @OneToMany(fetch = FetchType.EAGER) 
    @JoinColumn(name = "starId", referencedColumnName = "id", insertable = false, updatable = false) 
    private Set<Media> medias; 
} 

これはモデルクラスです。

@Service 
public class SuperfanStarService 
{ 
    @Autowired 
    private StarRepository starRepository; 

    @PersistenceContext 
    private EntityManager em; 

    @Transactional 
    public List<Star> getStars() 
    { 
     QStar qStar = QStar.star; 
     QMedia qMedia = QMedia.media; 

     List<Star> stars = 
       new JPAQuery(em) 
       .from(qStar) 
       .where(qStar.id.eq(19)) 
       .list(qStar); 

     return stars; 
    } 
} 

これは私のサービスクラスです。

20160915 20:52:59.119 [HTTP-NIO-8080-EXEC-1] DEBUG j.sqlonly - org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82) 9 star0_.idをid1_2_、star0_.background_imageをbackgrou2_2_、star0_.createdとして作成した3_2_、star0_.descriptionを とします。descript4_2_、star0_.nameをname5_2_、star0_.nicknameとして ニックネーム6_2_、star0_.thumbnail as thumbnai7_2_、star0_.updated as superfan_star star0_内側から updated8_2_はstar0_.id = medias1_.star_idここstar0_.id = 19

20160915 20にsuperfan_media medias1_に参加します: 52:59.173 [http-nio-8080-exec-1] DEBUG j.sqlonly - org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82) 9. select medias0_.star_idをstar_id11_2_0_、medias0_ medias0_.end_timeは is_pushe7_1_1_としてmedias0_.is_pushed end_time4_1_1_、is_appro5_1_1_としてmedias0_.is_approve、is_appro6_1_1_としてmedias0_.is_approved_final として、descript3_1_1_として medias0_.description、created2_1_1_としてmedias0_.created、id1_1_1_としてmedias0_.id、id1_1_0_として.ID 、medias0_.is_represent telepor12_1_1_、thumbna13_1_1_としてmedias0_.thumbnail、medias0_.titleとしてmedias0_.teleport_media_id release10_1_1_としてmedias0_.released is_repre8_1_1_、length9_1_1_として medias0_.length、star_id11_1_1_として medias0_.star_id、としてあなたが見ることができるように youtube17_1_1_、 superfan_mediaからyoutube18_1_1_としてmedias0_.youtube_title medias0_どこmedias0_.star_id = 19

としてmedias0_.youtube_id title14_1_1_、work_en15_1_1_としてmedias0_.work_end、work_st16_1_1_として medias0_.work_start、として、おそらく逆の更新のために、1回ではなく2回クエリを実行していますか? JPAモデルのクエリを1回だけ作成する方法はありますか?

+0

を:だから、あなたは、個々の@Getter@Setter@ToStringロンボクの注釈を使用し、それを削除し、必要なとき)(あなた自身の良識のequals()の実装とハッシュコードを書くことができますここで遊ぶ何か。関連アイテムがハッシュベースのコレクションに追加されたときにロードされる多くの追加データをトリガできるように、JPAエンティティでは危険なすべてのフィールドに基づいて、オーバーライドequalsとハッシュコードがあると信じているLombok @Dataがあります。 これを削除するとどうなりますか? –

+0

@AlanHayええ、私は、ロンボクが各スターのメディアを照会しているのでリストに問題を引き起こしていることを知りました。私はすべてを照会せずにロンボクを使う方法があるかどうかを見極めようとしていますが、方法はないようです。 – Aesis

+0

答えとして追加されました –

答えて

1

期待どおりに動作します。最初のクエリはデータベースからid = 19のStarエンティティを取得し、2番目のクエリはデータベースからそのStarエンティティのエンティティMediaを取得します。 (照会されているものを理解するために、SQLステートメントのログを注意深く見てください)。あなたはクラスStarmediasフィールド上FetchType.EAGERを指定

注:

@OneToMany(fetch = FetchType.EAGER) 
@JoinColumn(name = "starId", referencedColumnName = "id", insertable = false, updatable = false) 
private Set<Media> medias; 

イーガーフェッチを使用すると、1つのまたは複数のStarオブジェクトに対してクエリを実行する際に、すぐに休止状態リンクMediaオブジェクトを取得することを意味 - とは対照的に2番目のクエリはすぐには実行されませんが、必要な場合にのみ(mediasメンバ変数にアクセスしたとき)のみ必要です。

+0

ああ、ありがとう。私は、最初のクエリの内部結合がオブジェクトを取得するために必要なすべてであり、Mediaエンティティをリンクするために2番目のクエリが必要であることを認識していないと考えました。 – Aesis

1

受け入れられている回答がありますが、ここには他に何かがあると思われます。私はあなたがロンボク@Dataを持っていることに注意してください。equals()hashcode()は、関連アイテムがハッシュベースのコレクションに追加されたときにロードされる追加のデータをたくさんトリガできるJPAエンティティで危険なすべてのフィールドに基づいています。

ええ、私はそれが各スターのためにマスコミを問い合わせるだとしてロンボクはリストの問題を引き起こしていることが分かりました。私はすべてを照会せずにロンボクを使う方法があるかどうかを見極めようとしていますが、方法はないようです。

まず、私はあなたのエンティティのすべてのフィールドに基づいてequals()hashcode()を実施しないことをお勧め:それはあなたの問題の根本的な原因であると、とにかく意味がありません - あなたが可能なものを持っている場合は、固有のビジネスキーの上にそれらをベースにします。基本的に2つのエンティティは同じIDを持っていても同じですが、ここで参照してください:

The JPA hashCode()/equals() dilemma

また、ハッシュコード()不変のフィールドに基づくべきである - ここを参照してください:

http://blog.mgm-tp.com/2012/03/hashset-java-puzzler/を。

ロンボクの@Dataは、他の個々の注釈を集約するだけです。私は多分そこに疑う受け入れ答えがある一方

https://projectlombok.org/features/Data.html

関連する問題