Failed to lazily initialize a collection of role with SpringBoot
Asked Answered
D

3

8

I have a basic SpringBoot 2.0.3.RELEASE app using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine and package as an executable JAR file with these dependencies in the pom.xml.

I have a domain object called Company:

@Entity
@Table(name="t_company")
public class Company implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public Company() {
    }



    /**
     * @param companyName
     */ 
    public Company(String companyName) {
        super();
        this.name = companyName;
    }



    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotEmpty
    @Length(max = 100)
    private String name;


    @OneToMany(mappedBy = "company", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<User> users = new HashSet<>();

..
}

Repository Layer:

public interface CompanyRepository extends CrudRepository<Company, Long> {

    @Query("select co from Company co join co.users us where co = ?1")
    Company companyUsers (Company company);

}

Service Layer:

@Service
@Transactional(readOnly = true)
public class CompanyService {

     @Autowired
     private CompanyRepository companyRepository;

     public Company companyUsers (Company company) {
        return companyRepository.companyUsers(company);
     }

}

Junit file:

@Test
    public void testCompanyUsers() throws Exception {

        Iterable<Company> companies = companyService.findAll();
        Company company = companies.iterator().next();

        assertNotNull (company);

        company = companyService.companyUsers(company);
        assertTrue (((Collection<?>) company.getUsers()).size() > 0);           
    }

But when I run the test I get this error:

failed to lazily initialize a collection of role: com.cor.backend.persistence.domain.backend.Company.users, could not initialize proxy - no Session

Disused answered 16/8, 2018 at 12:23 Comment(0)
H
7

Please read one of my articles carefully: https://arnoldgalovics.com/lazyinitializationexception-demystified/

Your main problem is that you are trying to access an entity reference outside of a transaction. You have multiple options here:

  • Fetch the necessary data within the same logical transaction
  • Use FETCH JOIN in your JPQL query
  • Use projections

More reading about projections: https://arnoldgalovics.com/using-projections-in-your-data-access-layer/

Also, consider the performance impact of using projections: https://arnoldgalovics.com/how-much-projections-can-help/

Hospitium answered 18/8, 2018 at 14:35 Comment(0)
U
6

For springboot, we need to add @Transactional (org.springframework.transaction.annotation.Transactional) to the class where we used the lazy loaded property: testCompanyUsers()

i.e.

import org.springframework.transaction.annotation.Transactional;

...
@Transactional
public void testCompanyUsers() throws Exception {
...
Unheardof answered 8/8, 2020 at 18:36 Comment(0)
D
0

None of the methods above could work in my case. I printed an empty forEach loop before sending the data to the async mail function and the error disappeared.

myList.forEach(it -> {})
Dieball answered 25/5, 2022 at 11:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.