You need to make a lazy load for objects without causing org.hibernate.LazyInitializationException.

JPA configuration:

  @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean(); entityManagerFactory.setDataSource(dataSource); entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); entityManagerFactory.setJpaDialect(new HibernateJpaDialect()); entityManagerFactory.setPackagesToScan("education.web.platform"); entityManagerFactory.setJpaPropertyMap(hibernateJpaProperties()); return entityManagerFactory; } @Bean public JpaTransactionManager transactionManager(EntityManagerFactory emf) { JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(); jpaTransactionManager.setEntityManagerFactory(emf); return jpaTransactionManager; } private Map<String, ?> hibernateJpaProperties() { HashMap<String, String> properties = new HashMap<>(); properties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto")); properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql")); return properties; } @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(environment.getRequiredProperty("hibernate.connection.driver_class")); dataSource.setUrl(environment.getRequiredProperty("hibernate.connection.url")); dataSource.setUsername(environment.getRequiredProperty("hibernate.connection.username")); dataSource.setPassword(environment.getRequiredProperty("hibernate.connection.password")); return dataSource; } 

Example of a problem:

Load class:

 @Entity @Table(name = "theory_tasks") @PrimaryKeyJoinColumn(name = "task_id") public class TheoryTask extends Task { ... @OneToMany(targetEntity = ProbablyAnswer.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "task") private List<ProbablyAnswer> probablyAnswers = new ArrayList<>(); ... 

Object class for lazy loading:

 @Entity @Table(name = "probably_answers") public class ProbablyAnswer implements Serializable{ ... @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "task_id") private Task task; ... 

If the method that receives the list of objects in DAO marked @Transactional then when accessing the ProbablyAnswers list in TheoryTask they are not loaded and when passing it to the page org.hibernate.LazyInitializationException. thrown org.hibernate.LazyInitializationException.

If you mark the @Transactional method in a service or controller, then lazy loading is ignored and the entire object graph is recursively loaded.

The method by which I get the entity:

  public List<T> getAll(){ String genericClassName = persistentClass.toGenericString(); genericClassName = genericClassName.substring(genericClassName.lastIndexOf('.')+1); String hql = "FROM "+genericClassName; return entityManager.createQuery(hql,persistentClass).getResultList(); } 

Subsequently, the entity displayed on the html page.

  • Add your question, what methods you get from the database and how the entities are used in the future so that you can reproduce it. - MrFylypenko
  • @MrFylypenko added - Stanislav Sorokin

2 answers 2

Before using the resulting list, initialize it with the Hibernate.initialize(yourList) utility.

 public List<T> getAll(){ String genericClassName = persistentClass.toGenericString(); genericClassName = genericClassName.substring(genericClassName.lastIndexOf('.')+1); String hql = "FROM "+genericClassName; List<T> list = entityManager.createQuery(hql,persistentClass).getResultList(); Hibernate.initialize(list); return list; } 

    All entities with children can be obtained with a single query to the database. To do this, override your method in the implementation and specify which children you need to load, for example:

      public List<TheoryTask> getAll(){ String hql = "FROM TheoryTask t LEFT JOIN FETCH t.probablyAnswers"; return entityManager.createQuery(hql,TheoryTask.class).getResultList(); } 

    One query will be sent to the database and will be applied only for this method.