2015-10-11 2 views
1

Для того, чтобы преодолеть LazyInitializationException я решил использовать OpenEntityManagerInViewFilter - вот код из моего класса AppInitializer, который реализует WebApplicationInitializer:OpenEntityManagerInViewFilter - неопределенная EntityManagerFactory

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer implements WebApplicationInitializer { 

@Override 
public void onStartup(ServletContext servletContext) throws ServletException { 
    registerListener(servletContext); 
    registerDipsatcherServlet(servletContext); 
    registerOpenEntityManagerInViewFilter(servletContext); 
} 

private void registerListener(ServletContext servletContext) { 
    // Create the 'root' Spring application context 
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 
    // Manage the lifecycle of the root application context 
    servletContext.addListener(new ContextLoaderListener(rootContext)); 
} 

private void registerDipsatcherServlet(ServletContext servletContext) { 
    // Create the dispatcher servlet's Spring application context 
    AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext(); 
    dispatcherServlet.register(MvcConfiguration.class); 
    // Register and map the dispatcher servlet 
    ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet)); 
    customizeRegistration(dispatcher); 
    dispatcher.setLoadOnStartup(1); 
    dispatcher.addMapping("/"); 
} 

private void registerOpenEntityManagerInViewFilter(ServletContext servletContext) { 
    FilterRegistration.Dynamic registration = servletContext.addFilter("openEntityManagerInView", new OpenEntityManagerInViewFilter()); 
    registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD), false, "/*"); 
} 

@Override 
protected void customizeRegistration(ServletRegistration.Dynamic registration) { 
    registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); 
} 

@Override 
protected Class<?>[] getRootConfigClasses() { 
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
} 

@Override 
protected Class<?>[] getServletConfigClasses() { 
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
} 

@Override 
protected String[] getServletMappings() { 
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
} 

}

А вот класс @Configuration, который определяет фасоль:

@Configuration 
@EnableTransactionManagement 
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager", basePackages = "podraza.piotr.eshopper.repository") 
public class PersistenceConfiguration { 

    @Autowired 
    private JpaVendorAdapter jpaVendorAdapter; 

    @Value("${jpa.show-sql:false}") 
    private boolean showSql; 

    @Value("${jpa.datasource.url}") 
    private String databaseUrl; 

    @Value("${jpa.datasource.username}") 
    private String username; 

    @Value("${jpa.datasource.password}") 
    private String password; 

    @Value("${jpa.datasource.driverClassName}") 
    private String driverClassName; 
    /* 
    @Value("${jpa.hibernate.ddl-auto}") 
    private String hibernateDdlAuto; 
    */ 

    @Bean 
    public HibernateJpaVendorAdapter hibernateJpaVendorAdapter() { 
     HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); 
     hibernateJpaVendorAdapter.setShowSql(showSql); 
     //hibernateJpaVendorAdapter.getJpaPropertyMap().put("hibernate.hbm2ddl.auto", hibernateDdlAuto); 
     hibernateJpaVendorAdapter.setDatabase(Database.POSTGRESQL); 
     return hibernateJpaVendorAdapter; 
    } 

    @Bean 
    public DataSource dataSource() { 
     DriverManagerDataSource dataSource = new DriverManagerDataSource(databaseUrl, username, password); 
     dataSource.setDriverClassName(driverClassName); 
     return dataSource; 
    } 

    @Bean 
    public EntityManager entityManager() { 
     return entityManagerFactory().createEntityManager(); 
    } 

    @Bean 
    public EntityManagerFactory entityManagerFactory() { 
     LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean(); 
     lef.setDataSource(dataSource()); 
     lef.setJpaVendorAdapter(jpaVendorAdapter); 
     lef.setPackagesToScan("podraza.piotr.eshopper.entity"); 
     lef.setPersistenceUnitName("defaultPersistenceUnit"); 
     lef.afterPropertiesSet(); 
     return lef.getObject(); 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager() { 
     return new JpaTransactionManager(entityManagerFactory()); 
    } 

} 

Как указать этот компонент для фильтра э?

+0

Этот класс '@ Configuration' загружается' DispatcherServlet' или 'ContextLoaderListener'? –

+0

Я не уверен. Как я могу это определить? –

+0

Ваш 'AppInitializer' должен также создавать как' ContextLoaderListener', так и/или 'DispatcherServlet', который загружает конфигурацию. В идеале вы должны расширить 'AbstractAnnotationConfigDispatcherServletInitializer' и настроить, какие классы загружаются, с помощью которых (сохраняет некоторые строки кода :)). –

ответ

0

Вы используете классы Spring, и первое, что вы делаете, не использует его. Замените AppInitializer следующим.

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 

    @Override 
    protected void customizeRegistration(ServletRegistration.Dynamic registration) { 
     registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); 
    } 

    @Override 
    protected Class<?>[] getRootConfigClasses() { 
     return new Class[] {PersistenceConfiguration.class} 
    } 

    @Override 
    protected Class<?>[] getServletConfigClasses() { 
     throw new Class[] {MvcConfiguration.class}; 
    } 

    @Override 
    protected String[] getServletMappings() { 
    return new String[] {"/"}; 
    } 

    protected Filter[] getServletFilters() { 
    return return new Filter[] {new OpenentityManagerInViewFilter()}; 
    } 

} 

Кроме того, убедитесь, что в вашем MvcConfiguration вы снова не загружая PersistenceConfiguration класс, как это приведет к дублированию боба.

+0

После выполнения этой проблемы с undefined EntityManagerFactory ушел, но у меня все еще есть проблема с ленивой инициализацией, и PersistenceConfiguration не может разрешить мои свойства. –

+0

Поскольку 1, вы дважды загружаете конфигурацию, что приводит к созданию двух фабрик-менеджеров сущностей, один из которых открывает сеанс с базой данных, которая бесполезна, потому что вторая на самом деле будет использоваться. 2. Вы не определили 'PropertySourcePlaceholderConfigurer' в своей конфигурации, поэтому ваша' @ Value' никогда не будет заменена. –

+0

Я определил PropertySourcePlaceholderConfigurer в WebMvcConfiguration, и мое значение @ Value используется для правильной работы. Как я загружаю конфигурацию дважды? Я запутался прямо сейчас ;-) –