简体   繁体   English

Spring Data JPA是否忽略@Fetch注释?

[英]Does Spring Data JPA ignore @Fetch annotations?

I have the following JPA Mapping (getters and setters out for brevity purposes, the DDL also gets generated from the code which may/may not play a role): 我有以下JPA映射(为了简洁起见,使用getter和setter,DDL也从可能/可能不起作用的代码中生成):

Expense 费用

@Entity
public class Expense {

@Id
@GeneratedValue
private Long id;


private String name;
private Long amount;
private Boolean monthly;

@OneToOne
@JoinColumn(name = "category")
@Fetch(FetchMode.JOIN)
private Category category;

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<Label> labels = new ArrayList<>();
//constructor, getters and setters...
}

Category 类别

@Entity
public class Category {

@Id
private String name;

//constructor, getters and setters...
}

Label 标签

@Entity
public class Label {

@Id
private String name;
//constructor, getters and setters...

}

Usage with JpaRepository JpaRepository的用法

So I am using a JpaRepository that looks like this: 因此,我使用的JpaRepository如下所示:

public interface ExpensesRepository extends JpaRepository<Expense, Long> {

    @Query("SELECT e FROM Expense e LEFT JOIN FETCH e.category")
    List<Expense> findAllExpensesExploded();
}

When I use the default findAll() method of the JpaRepository, I get a n+1 select problem : 当我使用JpaRepository的默认findAll()方法时,出现一个n + 1选择问题

2017-01-03 19:35:22.665 DEBUG 26040 --- [nio-8080-exec-1] org.hibernate.SQL                        : select expense0_.id as id1_1_, expense0_.amount as amount2_1_, expense0_.category_name as category5_1_, expense0_.monthly as monthly3_1_, expense0_.name as name4_1_ from expense expense0_
2017-01-03 19:35:22.673 DEBUG 26040 --- [nio-8080-exec-1] org.hibernate.SQL                        : select category0_.name as name1_0_0_ from category category0_ where category0_.name=?
2017-01-03 19:35:22.674 TRACE 26040 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [Rent]
2017-01-03 19:35:22.682 DEBUG 26040 --- [nio-8080-exec-1] org.hibernate.SQL                        : select category0_.name as name1_0_0_ from category category0_ where category0_.name=?
2017-01-03 19:35:22.683 TRACE 26040 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [Insurance]

However, when I use my own findAllExpensesExploded() method I get a single SQL query: 但是,当我使用自己的findAllExpensesExploded()方法时,会得到一个SQL查询:

2017-01-03 19:35:22.691 DEBUG 26040 --- [nio-8080-exec-1] org.hibernate.SQL                        : select expense0_.id as id1_1_0_, category1_.name as name1_0_1_, expense0_.amount as amount2_1_0_, expense0_.category_name as category5_1_0_, expense0_.monthly as monthly3_1_0_, expense0_.name as name4_1_0_ from expense expense0_ left outer join category category1_ on expense0_.category_name=category1_.name

My expectation was for both findAll() and findAllExpensesExploded() to be executed with a single SQL query . 我的期望findAll()findAllExpensesExploded()都可以通过单个SQL查询执行。

  • My query worked because I seemed to have constructed it correctly 我的查询有效,因为我似乎已经正确构造了它
  • But why does the findAll() not work with the given mapping annotations? 但是为什么findAll()无法与给定的映射注释一起使用? Is it possible that Spring Data is ignoring the @Fetch annotation? Spring Data是否有可能忽略@Fetch注释?
  • An additional question that seems reasonable to ask is whether the default findAll() should only be used for simple entities? 一个似乎合理的问题是,默认的findAll()是否仅应用于简单实体? (where simple is defined as no associations). (其中简单定义为没有关联)。

The Default fetch mode is lazy. 默认提取模式是惰性的。 It's always a good practice to use @NamedEntityGraph and @EntityGraph annotations when working with Spring Data JPA.You can go through this 它总是使用一个很好的做法@NamedEntityGraph@EntityGraph使用Spring数据JPA.You工作可以顺利通过时,注释

whether the default findAll() should only be used for simple entities? (where simple is defined as no associations).

Fetch Mode - LAZY will only fire for primary table. 提取模式-LAZY仅针对主表触发。 If in the code you call any other method that has a parent table dependency then it will fire Fetch Mode - SELECT. 如果在代码中调用具有父表依赖项的任何其他方法,则它将触发“访存模式-SELECT”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM