Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Failed to lazily initialize a collection of role with SpringBoot

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

like image 507
en Peris Avatar asked Aug 16 '18 12:08

en Peris


2 Answers

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/

like image 193
Arnold Galovics Avatar answered Sep 22 '22 03:09

Arnold Galovics


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 {
...
like image 33
jxyu Avatar answered Sep 22 '22 03:09

jxyu