I'm using spring boot with JPA ( hibernate ) , Before I move to spring boot I was using Spring data JPA with hibernate and the default is to load property values eagerly and to load collections lazily.
in spring boot JPA the following is fetched eagerly by default why ? The roles will be returned inside the user but they should be null
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
That's the example I followed https://medium.com/@gustavo.ponce.ch/spring-boot-spring-mvc-spring-security-mysql-a5d8545d837d
And the application.properties I have edited to the follow :
# ===============================
# = JPA / HIBERNATE
# ===============================
spring.jpa.show-sql = true
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
# ==============================================================
# = Spring Security / Queries for AuthenticationManagerBuilder
# ==============================================================
spring.queries.users-query=select email, password, active from user where email=?
spring.queries.roles-query=select u.email, r.role from user u inner join user_role ur on(u.id=ur.user_id) inner join role r on(ur.role_id=r.id) where u.email=?
=========================================================================== I have tried to add this relation in the user Entity :
@Entity
@Table(name = "user")
@Getter
@Setter
public class User {
@OneToMany(mappedBy = "user")
private List<Test> tests;
}
the tests will be fetched eagerly in this :
@Transactional
@Override
public List<User> getAllUsers() {
List<User>users=userRepository.findAll();
return users;
}
I can't find why this is default instead of lazy loading.
You are mistaken. Every mapping that ends with toMany is by default fetched lazily.
Copied from the Spring source files:
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface ManyToMany {
// rest of the annotation properties are omitted for better readability
FetchType fetch() default LAZY;
}
Spring Boot nor Spring Data JPA changes the default behavior of resolving collections lazily. You probably have one of two the situations when using Spring Boot
@Transactional wasn't properly applied due to wrong configurationOpenEntityManagerInViewInterceptor for controllers.Spring Boot manages transactions for you and will have the processing of @Transactional turned on by default. So when inspecting the result inside the @Transactional method using a debugger the result will still be retrieved due to an ongoing transaction.
If that isn't the case you are seeing the effects of the OpenEntityManagerInViewInterceptor. Which leads to opening an EntityManager at the start of the request and close it after view rendering.
To disable this behavior (and assuming you are using a recent Spring Boot version) you can disable it by setting the spring.jpa.open-in-view property to false.
spring.jpa.open-in-view=false
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With