Java OpenEntityManagerViewFilter-未定义的EntityManagerFactory
为了克服LazyInitializationException,我决定使用OpenEntityManagerInViewFilter——以下是我的AppInitializer类中实现WebApplicationInitializer的代码:Java OpenEntityManagerViewFilter-未定义的EntityManagerFactory,java,spring,spring-mvc,filter,javabeans,Java,Spring,Spring Mvc,Filter,Javabeans,为了克服LazyInitializationException,我决定使用OpenEntityManagerInViewFilter——以下是我的AppInitializer类中实现WebApplicationInitializer的代码: public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer implements WebApplicationInitializer {
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.
}
如何为过滤器指明这个bean?您使用的是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()};
}
}
公共类AppInitializer扩展AbstractAnnotationConfigDispatcherServletInitializer{
@凌驾
受保护的无效自定义注册(ServletRegistration.Dynamic registration){
setInitParameter(“ThroweExceptionIfNoHandlerFound”、“true”);
}
@凌驾
受保护类[]getRootConfigClasses(){
返回新类[]{PersistenceConfiguration.Class}
}
@凌驾
受保护类[]getServletConfigClasses(){
抛出新类[]{MvcConfiguration.Class};
}
@凌驾
受保护的字符串[]getServletMappings(){
返回新字符串[]{”/“};
}
受保护的筛选器[]getServletFilters(){
返回新筛选器[]{new OpenentityManagerInViewFilter()};
}
}
还要确保在
mvc配置中
没有再次加载PersistenceConfiguration
类,因为这会导致bean重复 您使用的是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()};
}
}
公共类AppInitializer扩展AbstractAnnotationConfigDispatcherServletInitializer{
@凌驾
受保护的无效自定义注册(ServletRegistration.Dynamic registration){
setInitParameter(“ThroweExceptionIfNoHandlerFound”、“true”);
}
@凌驾
受保护类[]getRootConfigClasses(){
返回新类[]{PersistenceConfiguration.Class}
}
@凌驾
受保护类[]getServletConfigClasses(){
抛出新类[]{MvcConfiguration.Class};
}
@凌驾
受保护的字符串[]getServletMappings(){
返回新字符串[]{”/“};
}
受保护的筛选器[]getServletFilters(){
返回新筛选器[]{new OpenentityManagerInViewFilter()};
}
}
还要确保在
mvc配置中
没有再次加载PersistenceConfiguration
类,因为这会导致bean重复 @Configuration
类是由DispatcherServlet
或ContextLoaderListener
加载的?我不确定。如何确定?您的AppInitializer
还应该构造加载配置的ContextLoaderListener
和/或DispatcherServlet
。理想情况下,您可以扩展AbstractAnnotationConfigDispatcherServletInitializer
,并配置加载哪些类(为您保存一些代码行:)。它会同时构造这两个类。我已经发布了完整的代码。你到底为什么有这个玩意儿?你是在扩展一个类,并通过自己实现所有东西来破坏它的功能吗?该类未加载或仅由DispatcherServlet
加载,这使得OpenEntityManagerViewFilter
无法检测该类,因为这要求EntityRangerFactory在根上下文中可用。该@Configuration
类由DispatcherServlet
加载,或ContextLoaderListener
?我不确定。如何确定?您的AppInitializer
还应该构造加载配置的ContextLoaderListener
和/或DispatcherServlet
。理想情况下,您可以扩展AbstractAnnotationConfigDispatcherServletInitializer
,并配置加载哪些类(为您保存一些代码行:)。它会同时构造这两个类。我已经发布了完整的代码。你到底为什么有这个玩意儿?你是在扩展一个类,并通过自己实现所有东西来破坏它的功能吗?类未加载或仅由DispatcherServlet
加载,这使得OpenEntityManagerViewFilter无法检测到该类,因为这要求EntityRangerFactory在根上下文中可用。在对未定义的EntityManagerFactory执行该操作后,该问题消失了,但我仍然对它有问题初始化和PersistenceConfiguration无法解析我的属性。因为1,您加载了两次配置,导致两个实体管理器工厂,其中一个打开了与数据库的会话,这是无用的,因为第二个将实际使用。2.您尚未在配置中定义PropertySourcePlaceHolderConfiguration
,因此您的@Value
永远不会被替换。我已在WebMVC配置中定义了PropertySourcePlaceHolderConfiguration,并且我的@Value用于正常工作。如何加载配置两次?我现在很困惑;-)一次是通过ContextLoaderLIstener
,我猜是由于@组件在DispatcherServlet
中再次扫描
。CLL中的一个由过滤器使用(无替换值),DS中的一个由其他所有内容使用。理想情况下,您的服务、存储库、基础结构bean(数据源、实体管理器、连接工厂)应该由CLL加载,DS只加载与web相关的内容。非常感谢您的帮助。我将扩展我在这方面的知识,因为我看到有很多事情我可能已经忽略了,因为我刚刚开始了我的Spring冒险;-)我不想再给你添麻烦了,但如果我遇到这样的问题,除了Stack之外,还有什么方法可以联系你吗?再次感谢,您帮了我很大的忙。在使用未定义的EntityManagerFactory解决了这个问题之后,我仍然存在延迟初始化问题,PersistenceConfiguration无法解析我的属性。因为1,您加载了两次配置,导致