LazyInitializationException: could not initialize proxy - no Session
Asked Answered
F

4

20

I use spring-data-jpa with spring-boot(v2.0.0.RELEASE), I just wrote a CRUD demo on MySQL, but an exception occurs during runtime, source code as follows:

Source code

User.java

@Entity
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private Integer id;
    private String username;
    private String password;

    ...getter&setter
} 

UserRepository.java

public interface UserRepository extends JpaRepository<User, Integer> {

}

UserServiceTest.java

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void getUserById() throws Exception{
        userRepository.getOne(1);
    }

}

application.yml

spring:
  datasource:
    username: ***
    password: ***
    driver-class-name: com.mysql.jdbc.Driver
    url: ********
  thymeleaf:
    cache: false
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update

Exception details

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:155)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:268)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73)
at cn.shuaijunlan.sdnsecuritysystem.domain.po.User_$$_jvstc90_0.getUsername(User_$$_jvstc90_0.java)
at cn.shuaijunlan.sdnsecuritysystem.service.UserServiceTest.getUserById(UserServiceTest.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

I try to another method userRepository.findOne(1), it can run successfully.

Fleischer answered 18/4, 2018 at 8:17 Comment(2)
Try to add @Transactional to your test method...Stauffer
@Stauffer Add @Transactional to the unit test method, it can run successfully, can you give more details about why it can run without exception?Fleischer
S
32

You can add @Transactional annotation to your test method to avoid this exception.

Method getOne return the 'reference' (proxy) of the entity which properties can be lazy loaded. See it code - it uses getReference method of EntityManager. From it javadoc:

Get an instance, whose state may be lazily fetched.

In Spring the implementation of EntityManager is org.hibernate.internal.SessionImpl - so without the Session the Spring can not get this method.

To have a session you can just create a transaction...

Stauffer answered 18/4, 2018 at 12:55 Comment(4)
But if my test uses the @Transactional annotation, doesn't that mean the test is only valid for transactional queries?Insomuch
@Insomuch every method in JpaRepository is transactionalStauffer
In my case, adding @Transactional to the service itself helpedWhodunit
But why is it helpful at this point? Does the @Transaction annotation create a session? AFAIK this annotation handle rollback things but maybe my knowledge isn't enough.Ogive
D
4

Your test should be like this:

@RunWith(SpringRunner.class)    


@SpringBootTest
@Transactional    

public class QuestionTesting {   

    @Test    
    public void test() {    

    }    
}    
Decompound answered 14/8, 2019 at 19:50 Comment(1)
Please try to use code block formatting on all the code in your answer. stackoverflow.com/editing-help#codeEscharotic
S
3

just add in application properties spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

Squatter answered 28/9, 2021 at 6:41 Comment(2)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Morvin
A couple of recommendations not to do this... thorben-janssen.com/lazyinitializationexception and vladmihalcea.com/… - more discussion on this answer: https://mcmap.net/q/277806/-spring-data-jpa-quot-could-not-initialize-proxy-no-session-quot-with-methods-marked-as-transactionalStays
I
-2

In the service class please add a setter for entity manager by using the annoattion @PersistenceContext. To be specific, use

 @PersistenceContext(type = PersistenceContextType.EXTENDED)

In this way, you can access lazy property.

Ibby answered 18/4, 2018 at 9:17 Comment(3)
Your example would be more helpful if you included whatever it is you're annotating. Do I apply this to the class? And what do you mean by "the service class"?Insomuch
Service class is the class having the @Service annotation. I assume you knoe spring containers and spring classes.Ibby
The question does not have a service class.Tachycardia

© 2022 - 2024 — McMap. All rights reserved.