2016-03-03 3 views
1

Так что у меня это два класса:Не удалось записать содержание: не удалось лениво инициализировать коллекцию роли с помощью OpenEntityManagerInViewFilter

Sample

@Entity 
@Table(name="sample") 
public class Sample implements Serializable { 

@Id 
@GeneratedValue 
@Column(name="sample_id") 
private Long sample_id; 
@Column(name="id") 
private String id; 
@Column(name="description") 
private String description; 
@ManyToOne 
@JoinColumn(name="dna_study_id") 
private DNA_Study study; 
...Getters and setters ... 

DNA_Study

@Entity 
@Table(name = "dna_study") 
public class DNA_Study implements Serializable { 

@Id 
@GeneratedValue 
@Column(name="dna_study_id") 
private Long id; 
@Column(name="name") 
private String name; 
@Column(name="description") 
private String description; 
@Column(name="date") 
private Date date; 
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
@JoinColumn(name = "dna_study_id") 
private List<Sample> samples; 

I хочу получить всю DNA_Study из моей базы данных, имея это DAO:

@Repository 
public interface DNA_StudyDAO extends CrudRepository<DNA_Study, Long>{ } 

и это RestController:

@RestController 
public class AnalysisController { 

    ClassPathXmlApplicationContext context; 

    @CrossOrigin 
    @RequestMapping("/getanalysis") 
    public ArrayList<DNA_Study> getAnalysis() { 

     context = new ClassPathXmlApplicationContext("applicationContext.xml"); 
     DNA_StudyDAO dao = context.getBean(DNA_StudyDAO.class); 
     return (ArrayList<DNA_Study>) dao.findAll(); 
    } 

Как когда я называю его я получаю "Не удалось записать содержание: не удалось лениво инициализировать коллекцию роли" Я пытался для изменения моего DAO, поэтому метод findAll() изменяется на:

@Override 
@Query("select d from DNA_Study d join fetch d.samples") 
Iterable<DNA_Study> findAll(); 

с использованием t его исключение не выбрасывается, но метод вызова создает бесконечный цикл, так как создание DNA_Study подразумевает загрузку его образцов, и каждый образец загружает его DNA_Study и т. д., поэтому он прерывается. Поэтому я полагаю, мне нужно будет добавить OpenEntityManagerInViewFilter и отменить переопределение FindAll(), попытался добавить к моему SpringBootServletInitializer класс:

@Override 
public void onStartup(ServletContext servletContext) throws ServletException 
{ 
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 
    rootContext.register(Application.class); 
    rootContext.setServletContext(servletContext); 
    ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext)); 
    dispatcher.setLoadOnStartup(1); 
    dispatcher.addMapping("/"); 

    FilterRegistration.Dynamic filter = servletContext.addFilter("openEntityManagerInViewFilter", OpenEntityManagerInViewFilter.class); 
    filter.setInitParameter("singleSession", "true"); 
    filter.addMappingForServletNames(null, true, "dispatcher"); 
    servletContext.addListener(new ContextLoaderListener(rootContext)); 
} 

Но когда я делаю вызов я все еще получаю "не удалось инициализировать лениво сборник роли "

Как правильно добавить OpenEntityManagerInViewFilter?


EDIT

класс, который расширяет SpringBootServletInitializer:

@Override 
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 
     return application.sources(GemDomusServerApplication.class); 
    } 

    @Override 
    public void onStartup(ServletContext servletContext) throws ServletException 
    { 
     AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 
     rootContext.register(Application.class); 
     rootContext.setServletContext(servletContext); 
     ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext)); 
     dispatcher.setLoadOnStartup(1); 
     dispatcher.addMapping("/"); 
     FilterRegistration.Dynamic filter = servletContext.addFilter("openEntityManagerInViewFilter", OpenEntityManagerInViewFilter.class); 
     filter.setInitParameter("singleSession", "true"); 
     filter.setInitParameter("entityManagerFactoryBeanName", "entityManagerFactory"); 
     filter.setInitParameter("flushMode", "auto"); 
     filter.addMappingForServletNames(null, true, "dispatcher"); 
     servletContext.addListener(new ContextLoaderListener(rootContext)); 
     servletContext.addListener(new RequestContextListener()); 
    } 

    public static void main(String[] args) { 

     SpringApplication.run(GemDomusServerApplication.class, args); 
    } 

applicationContext.xml бобы участвуют

<bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="persistenceUnitName" value="jpaData" /> 
     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
     </property> 
     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop> 
       <prop key="hibernate.show_sql">true</prop> 
       <prop key="hibernate.format_sql">true</prop> 
       <prop key="hibernate.hbm2ddl.auto">update</prop> 
      </props> 
     </property> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 
<bean id="dataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName"> 
      <value>org.postgresql.Driver</value> 
     </property> 
     <property name="url"> 
      <value>**</value> 
     </property> 
     <property name="username"> 
      <value>**</value> 
     </property> 
     <property name="password"> 
      <value>**</value> 
     </property> 
    </bean> 

persistence.xml

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="1.0" 
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> 

    <persistence-unit name="jpaData"/> 

</persistence> 

ответ

0

Ну, наконец, после попытки этого работал: делает Нетерпеливые коллекции инициализации стенда (образец и DNA_Study и изменение AnalysisController к:

@CrossOrigin 
    @RequestMapping("/getanalysis") 
    public JsonArray getAnalysis() { 

     context = new ClassPathXmlApplicationContext("applicationContext.xml"); 
     DNA_StudyDAO dao = context.getBean(DNA_StudyDAO.class); 
     ArrayList<DNA_Study> result = (ArrayList<DNA_Study>) dao.findAll(); 
     JsonArrayBuilder datasourcesBuilder = Json.createArrayBuilder(); 
     for(DNA_Study study : result) { 
      datasourcesBuilder 
      .add(Json.createObjectBuilder() 
       .add("name", study.getName()) 
       .add("description", study.getDescription()) 
       .add("size", String.valueOf(study.getSamples().size()))); 
     } 
     return datasourcesBuilder.build(); 
} 

Не удалось найти способ сделать это с ленивой инициализацией

0

Ваша проблема очень похожа на этот один Lazy Initialisation with OpenEntityManagerInViewFilter?

Другой вариант, мой любимый, чтобы позвонить в спящий режим.инициализировать (Object) внутри DAO или менеджер оборачивать ваши DAO с аннотацией @Transactional

+0

Так что я должен вызвать findAll() и перебрать любой элемент с Hiebernate.initialize (Object)? – Dexter

+0

этот запрос должен быть достаточным, чтобы заставить EAGER извлекать ваши коллекции образцов " выберите d из DNA_Study d join fetch d.sampl es ", но в случае, если это не работает, вы можете заставить это в коде путем итерации объекта и вызова Hibernate.initialize –

+0

Но мне нужна ленивая инициализация. В ссылке они добавляют фильтр, так что я и не работал. – Dexter

Смежные вопросы