-1

I am working on a Spring Boot project using Spring Data JPA and I have the following problem trying to retrieve data.

I have this User class mapping a portal_user DB table:

@Entity
@Table(name = "portal_user")
@Getter
@Setter
public class User implements Serializable {
     
    private static final long serialVersionUID = 5062673109048808267L;
    
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    
    @Column(name = "first_name")
    private String firstName;
    
    @Column(name = "middle_name")
    private String middleName;
    
    @Column(name = "surname")
    private String surname;
    
    @Column(name = "sex")
    private char sex;
    
    @Column(name = "birthdate")
    private Date birthdate;
    
    @Column(name = "tex_code")
    private String taxCode;
    
    @Column(name = "e_mail")
    private String eMail;
    
    @Column(name = "contact_number")
    private String contactNumber;
    
    @Temporal(TemporalType.DATE)
    @Column(name = "created_at")
    private Date createdAt;
    
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
    @JsonManagedReference
    private Set<Address> addressesList = new HashSet<>();
    
    //@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    //@JsonManagedReference
    //private Set<User_UserType> userToUserTypeAssociation = new HashSet<>();
    
    @ManyToMany(cascade = { CascadeType.MERGE })
    @JoinTable(
        name = "portal_user_user_type", 
        joinColumns = { @JoinColumn(name = "portal_user_id_fk") }, 
        inverseJoinColumns = { @JoinColumn(name = "user_type_id_fk") }
    )
    Set<UserType> userTypes;
    

    public User() {
        super();
        // TODO Auto-generated constructor stub
    }


    public User(String firstName, String middleName, String surname, char sex, Date birthdate, String taxCode,
            String eMail, String contactNumber, Date createdAt) {
        super();
        this.firstName = firstName;
        this.middleName = middleName;
        this.surname = surname;
        this.sex = sex;
        this.birthdate = birthdate;
        this.taxCode = taxCode;
        this.eMail = eMail;
        this.contactNumber = contactNumber;
        this.createdAt = createdAt;
    }

}

As you can see into this entity class there are some relationship, for example this @OnetoMany relationship:

@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
@JsonManagedReference
private Set<Address> addressesList = new HashSet<>();

This is my Address entity class mapping the address table on my DB:

@Entity
@Table(name = "address")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor 
public class Address implements Serializable {
     
    private static final long serialVersionUID = 6956974379644960088L;
    
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    
    @Column(name = "country")
    private String country;
    
    @Column(name = "province")
    private String province;
    
    @Column(name = "zip_code")
    private String zipCode;
    
    @Column(name = "street")
    private String street;
    
    @Column(name = "notes")
    private String notes;
    
    //@Column(name = "fk_user_id")
    //private int fkUserId;
    
    @ManyToOne
    @EqualsAndHashCode.Exclude          // Needed by Lombock in "Many To One" relathionship to avoid error
    @JoinColumn(name = "fk_user_id", referencedColumnName = "id")
    @JsonBackReference
    private User user;

    public Address(String country, String province, String zipCode, String street, String notes, User user) {
        super();
        this.country = country;
        this.province = province;
        this.zipCode = zipCode;
        this.street = street;
        this.notes = notes;
        this.user = user;
    }


}

I created this unit test method to test the retrieve of all the records into my portal_user table (and the information caming from the relationship):

@Test
@Order(2)
public void RetrieveAllUsers() {
    
    List<User> usersList = this.userRepository.findAll();
    System.out.println(usersList.get(0).getAddressesList());
    System.out.println(usersList.get(0).getUserTypes());
    assertTrue(true);
    
}

The findAll() method seems works and the list is retrieved but using the debugger I cannot see the value of the two field representing a relationship, this is what I am ontaining in the "expression" tab of the debugger.

usersList   (id=180)    
    [0] User  (id=193)  
        addressesList   PersistentSet  (id=199) 
            Error   Exception occurred: com.sun.jdi.InvocationException: Exception occurred in target VM occurred invoking method.. 
        birthdate   Timestamp  (id=204) 
        contactNumber   329123456" (id=208) 
        createdAt   Date  (id=213)  
        eMail   xxx@gmail.com" (id=215) 
        firstName   Luca" (id=216)  
        id  25  
        middleName  null    
        sex M   
        surname Verdi" (id=217) 
        taxCode XXX" (id=218)   
        userTypes   PersistentSet  (id=220) 
            Error   Exception occurred: com.sun.jdi.InvocationException: Exception occurred in target VM occurred invoking method.. 
    [1] User  (id=196)  
    [2] User  (id=197)  
Add new expression      

As you can see, the value of the addressesList and of the userTypes fields representing my relationship is something like:

Error   Exception occurred: com.sun.jdi.InvocationException: Exception occurred in target VM occurred invoking method.. 

As you can see in the previous unit test method code I then tried to access it by:

usersList.get(0).getAddressesList())

but when this code is performed I obtains this exception:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.easydefi.users.entity.User.addressesList, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
    at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:327)
    at java.base/java.lang.String.valueOf(String.java:3365)
    at java.base/java.io.PrintStream.println(PrintStream.java:1047)
    at com.easydefi.users.tests.RepositoryTests.UserRepositoryTest.RetrieveAllUsers(UserRepositoryTest.java:86)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:84)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

What is the problem? What am I missing? How can i try to fix this issue?

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • Because your releations are declared as lazy. You can only load them lazy if you have a transaction and access the fields in the same transaction in which you fetched the entity initially. Take a look at https://stackoverflow.com/a/2991015/7082956 – Valerij Dobler Nov 09 '21 at 16:15
  • The EntityManager was closed by the time you did `usersList.get(0).getAddressesList()` and `usersList.get(0).getUserTypes()`. This may help you: https://vladmihalcea.com/the-best-way-to-handle-the-lazyinitializationexception/ – Matheus Nov 09 '21 at 16:32

1 Answers1

1

You're trying to access to a lazy-loaded object outside of the context of an open Hibernate session. To avoid this error you have some choices, two of them:

1. Using FetchType.EAGER Strategy

  @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
  @JsonManagedReference
  private Set<Address> addressesList = new HashSet<>();

2. Using Join Fetching

  SELECT u FROM User u JOIN FETCH u.adressesList
galaxy
  • 159
  • 1
  • 7