0

I'm developing a Java application using Spring Boot and JPA (Java Persistence API) with Hibernate. I have an entity Project that contains a one-to-many relationship with Activity.

I encounter the following error:


java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:773) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:754) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294) ~[spring-boot-3.1.0.jar:3.1.0]
    at org.classroomcreative.ClassRoomCreativeStart.main(ClassRoomCreativeStart.java:25) ~[classes/:na]
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.classroomcreative.domain.Project.activities: could not initialize proxy - no Session
    at org.hibernate.collection.spi.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:635) ~[hibernate-core-6.2.2.Final.jar:6.2.2.Final]
    at org.hibernate.collection.spi.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218) ~[hibernate-core-6.2.2.Final.jar:6.2.2.Final]
    at org.hibernate.collection.spi.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:615) ~[hibernate-core-6.2.2.Final.jar:6.2.2.Final]
    at org.hibernate.collection.spi.AbstractPersistentCollection.read(AbstractPersistentCollection.java:136) ~[hibernate-core-6.2.2.Final.jar:6.2.2.Final]
    at org.hibernate.collection.spi.PersistentBag.toString(PersistentBag.java:610) ~[hibernate-core-6.2.2.Final.jar:6.2.2.Final]
    at java.base/java.lang.StringConcatHelper.stringOf(StringConcatHelper.java:453) ~[na:na]
    at org.classroomcreative.domain.Project.toString(Project.java:12) ~[classes/:na]
    at org.classroomcreative.ClassRoomCreativeStart.lambda$demo$0(ClassRoomCreativeStart.java:48) ~[classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:770) ~[spring-boot-3.1.0.jar:3.1.0]
    ... 5 common frames omitted

In my Project class, I have the following configuration for the one-to-many relationship:


@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class Project {


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

    String target;

    List<String> images;

    @OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
    List<Activity> activities;

}

The Activity class is also defined as an entity with the following configuration:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Activity {

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

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "project_id")
    Project project;

    String development;

    String targets;

    String basicKnowledge;

    String assessment;
}

And this is the test I'm running and getting the error:

@SpringBootApplication
@Slf4j
public class ClassRoomCreativeStart {
    public static void main(String[] args) {
        SpringApplication.run(ClassRoomCreativeStart.class, args);
    }


    @Bean
    public CommandLineRunner demo(ProjectRepository projectRepository, ActivityRepository activityRepository) {
        return (args) -> {
            ProjectServiceImpl service = new ProjectServiceImpl(projectRepository);

            Activity activity1 = new Activity();
            activity1.setTargets("Target for Activity 1");

            Project project = new Project();
            project.setTarget("Sample Project");
            project.setActivities(List.of(activity1));

            service.saveProject(project);



            // Retrieve projects and activities
            log.info("Projects found with findAll():");
            log.info("-------------------------------");
            for (Project p : service.getProjects()) {
                log.info(p.toString());
            }

        };
    }
}

My service is:

@Service
public class ProjectServiceImpl {
    private final ProjectRepository repository;

    public ProjectServiceImpl(ProjectRepository repository){
        this.repository = repository;
    }

    @Transactional
    public Project saveProject(Project project){
        return repository.save(project);
    }

    @Transactional(readOnly = true)
    public List<Project> getProjects(){
        return repository.findAll();
    }
}

I have tried all the solutions mentioned in How to solve the “failed to lazily initialize a collection of role” Hibernate exception, but the issue persists.

Fjgonmir
  • 3
  • 3

1 Answers1

0

adding fetchType of Eager in the @OneToMany end should solve lazy initialization problem

@OneToMany(fetch = FetchType.EAGER, mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
    List<Activity> activities;

but you also need to override toString method of activity class to prevent circular dependency between them (exclude project attribute from toString method in the Activity class)

Ahmed Nabil
  • 457
  • 1
  • 9
  • Thanks @Ahmed Nabil for your answer, when I set the load eager when I print the project object the activities are empty. Example:`Project(id=1, target=Sample Project, images=null, activities=[])`. – Fjgonmir Jul 21 '23 at 16:37
  • sorry for late answer, you are using bi-directional relationship between Project and activities, so you should always keep synch between the 2 ends, so whenever you are adding activity to activities List, you should also setProject on that activity – Ahmed Nabil Jul 25 '23 at 06:09
  • Thanks , working – Fjgonmir Jul 27 '23 at 21:23
  • Happy to hear that. U should mark it as accepted answer if it helps – Ahmed Nabil Jul 28 '23 at 05:23