简体   繁体   中英

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):

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

So I am using a JpaRepository that looks like this:

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 :

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:

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 .

  • My query worked because I seemed to have constructed it correctly
  • But why does the findAll() not work with the given mapping annotations? Is it possible that Spring Data is ignoring the @Fetch annotation?
  • An additional question that seems reasonable to ask is whether the default findAll() should only be used for simple entities? (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

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. If in the code you call any other method that has a parent table dependency then it will fire Fetch Mode - SELECT.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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