Spring Hibernate:重新加载实体映射

Neo*_*oP5 5 java spring hibernate spring-mvc

在Web应用程序上,我们使用Spring 3.2和Hibernate 4.1.1并实现类似插件的体系结构。可以在运行时添加和删除插件。对于每个模块,我们定义了一个单独的类加载器,并在spring上创建了单独的子应用程序上下文。完整的配置使用注释完成,不再为bean提供XML配置。

Spring Hibernate配置类

@Configuration
@EnableTransactionManagement
public class HibernateConfigurationFactory {

@Bean
public JndiObjectFactoryBean dataSource() {
    JndiObjectFactoryBean ds = new JndiObjectFactoryBean();
    ds.setJndiName("java:jboss/datasources/OurOwnDS");
    ds.setResourceRef(true);
    return ds;
}

@Bean
public LocalSessionFactoryBean sessionFactory() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setPackagesToScan("com.foo.bar");
    sessionFactory.setDataSource((DataSource) dataSource().getObject());

    Properties hibernateProperties = new Properties();
    hibernateProperties.put("hibernate.hbm2ddl.auto", "update");

    sessionFactory.setHibernateProperties(hibernateProperties);

    return sessionFactory;
}

@Bean
public HibernateTransactionManager transactionManager() {
    HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory().getObject());
    return transactionManager;
}

}
Run Code Online (Sandbox Code Playgroud)

现在的问题是:一些插件包含它们自己的实体(+ DAO)类,这些类在运行时随模块一起添加。

是否可以在休眠状态下创建某种单独的上下文(就像我们在春季那样),甚至可以添加/重新加载其他实体类?

重新加载EntityManager是否可以满足我的需求?但是在上下文中已经加载的实体会发生什么?

感谢您的帮助和提前评论。

更新: 其实我做了以下并解决了这个问题(但后来又遇到了另一个问题。)。

我为每个模块/上下文创建一个新的DataSource + SessionFactory + TransactionManager,并将它们插入到新的子ApplicationContext中。现在,我使用类加载器扫描所有带注释的类,并通过使用手动在应用程序上下文和会话工厂上注册它们

LocalSessionFactorybean#setAnnotatedClasses(...)
Run Code Online (Sandbox Code Playgroud)

这个效果很好...但是...

下一个问题: 我得到一个ClassNotFoundException,这似乎是一个类加载器问题。Hibernate使用系统类加载器,而不是我自己的pluginClassloader。

有人知道如何向Hibernate注入自己的类加载器吗?

Neo*_*oP5 1

如果有人需要类似的解决方案,只需更新。

我通过执行以下操作解决了这种情况:

  • 创建一个新的 ApplicationContext,以当前根上下文为父级
  • 向上下文引入新的类加载器和自己的资源加载器
  • 以编程方式,我为新上下文创建一个新的会话工厂和事务管理器

        // create the datasource bean
        BeanDefinitionBuilder dataSourceBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(DataSourceConfiguration.class, "createDataSource");
        dataSourceBeanBuilder.addConstructorArgValue(descriptor.getDataSourceDescriptor().getJNDILookupName());
        dataSourceBeanBuilder.addConstructorArgValue(descriptor.getDataSourceDescriptor().isResourceRef());
        moduleContext.registerBeanDefinition("dataSource", dataSourceBeanBuilder.getBeanDefinition());
    
        // now build the sessionFactor
        BeanDefinitionBuilder sessionFactoryBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(SessionFactoryFactory.class, "createSessionFactory");
        sessionFactoryBeanBuilder.addConstructorArgReference("dataSource");
        sessionFactoryBeanBuilder.addConstructorArgValue(module.getKey());
        sessionFactoryBeanBuilder.addConstructorArgValue(moduleContext.getModuleResourceLoader());
        sessionFactoryBeanBuilder.addConstructorArgValue(annotatedClasses);
        moduleContext.registerBeanDefinition("sessionFactory", sessionFactoryBeanBuilder.getBeanDefinition());
    
        // now build the transactionManager
        BeanDefinitionBuilder transactionManagerBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(HibernateConfigurationFactory.class, "createTransactionManager");
        transactionManagerBeanBuilder.addConstructorArgReference("sessionFactory");
        moduleContext.registerBeanDefinition("transactionManager", transactionManagerBeanBuilder.getBeanDefinition());
    
    Run Code Online (Sandbox Code Playgroud)
    • 调用 context.refresh() 加载并初始化所有实体
    • 调用 context.start() 启动新的上下文