当前位置: 首页 > 知识库问答 >
问题:

Spring HiberNate:重新加载实体映射

戚勇
2023-03-14

在web应用程序上,我们使用Spring 3.2和Hibernate 4.1.1,并实现了一个类似插件的架构。插件可以在运行时添加和删除。对于每个模块,我们定义了一个单独的类加载器,并在spring上创建了单独的子应用程序上下文。完整的配置是使用注释完成的,不再需要对beans进行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;
}

}

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

是否可以在hibernate上创建某种单独的上下文(就像我们在spring上所做的那样),甚至添加/重新加载其他实体类?

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

提前感谢任何帮助和评论。

更新:实际上,我做了以下工作并解决了问题(但后来遇到了另一个问题)。

我为每个模块/上下文创建一个新的DataSource SessionFactory TransactionManager,并将它们插入到新的子ApplicationContext中。现在我使用类加载器扫描所有带注释的类,并使用

LocalSessionFactorybean#setAnnotatedClasses(...)

这效果很好...但。。。

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

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

共有2个答案

沈子实
2023-03-14

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

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

>

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

        // 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());
    
    • 调用 context.refresh() 来加载和初始化所有实体
    • 调用 context.start() 以启动新上下文

  • 薛博赡
    2023-03-14

    注入环境并将其用作Hibernate资源的额外来源是否可行?

    @Configuration
    @EnableTransactionManagement
    public class HibernateConfigurationFactory {
    
        @Autowired
        Environment env;
    
        @Bean 
        public LocalSessionFactoryBean sessionFactory() {
            LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
            sessionFactory.setPackagesToScan("com.foo.bar");
            if (env.containsProperty("some.extra.classes.property") {
                sessionFactory.setAnnotatedClasses(some extrapolation here);
                // Or similarly add extra packages for scanning
                ...
            }
        }
    }
    

    至于额外的DAO beans,可以使用@Profile,或者——如果使用Spring 4——使用@Conditional。

    编辑

    环境不是您创建的,它是“为您准备的”。它基本上是属性源和配置文件集的容器。

    一个好的参考点是Spring参考留档,即IoC容器章节。您还可以查看SpringSource博客。Chris Beams的与Spring 3.1相关的好文章很少,但大部分内容都在那里。

    例如,您可以使用以下内容来引导子应用程序上下文:

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    ConfigurableEnvironment environment = context.getEnvironment();
    
    // this is how you set different properties per a sub context. 
    Map subContextMap = new HashMap();
    subContextMap.put("some.extra.classes.property", [unique value here]);
    environment.getPropertySources().addFirst(new MapPropertySource("SUB_CTX_MAP", subContextMap);
    
    // this is the generic configuration class(es).
    context.register(HibernateConfigurationFactory.class);
    
    context.refresh();
    
     类似资料:
    • 我已经用Spring Security模块实现了OAuth2密码授权。我添加了自己的UserDetails和UserDetailsService (jdbc)实现。我将用户注入到我控制器中: 其中User是我的UserDetails实现。现在我想添加在不刷新令牌的情况下更改用户数据的可能性。 我尝试更新校长: 但它不起作用,当我调用另一个控制器方法时,它会返回旧的User对象。 有没有办法在不刷新

    • 我使用Hibernate已经有一段时间了,而且非常成功。然而,我昨天遇到了一个问题,这里的答案将在将来节省大量调试时间。 我忘了在我的hibernate中添加hibernate映射。新实体的cfg。 当我试图加载这个实体时,我本以为会得到某种运行时异常,但它却什么也没加载,继续运行,好像一切都很好。 我正在使用以下代码加载实体。 我想一个错误,如果我尝试加载一个实体,没有映射在我的hibernat

    • 我正在使用模型映射器(http://modelmapper.org/)将具有延迟加载对象列表(通过Hibernate)的实体映射到具有modelmapper.map()的DTO。 输出dto的列表为空值,但实体的列表已填充。当我改为“急切加载”时,一切正常,但我的查询太大,所以这不是一个选项。 有人知道模型映射器如何映射代理的Hibernate实体类吗? 这是我的父实体: 运输署署长: 这是我如何

    • 我在Hibernate重新加载查询中的实体时遇到问题,即使它们是作为主查询的一部分获取的。 实体如下(简化) 这是对父/子关系的闭包表进行建模。 我制定了以下一些标准 这导致以下SQL查询 看起来它正确地实现了连接获取。但是当我执行 我在结果集中的每行SQL日志中看到这些条目之一 看起来即使DataContents被标记为懒加载,它也在急切地加载。 因此,我要么希望在我的查询中以某种方式获取加入数

    • 我在使用spring-boot-devtools时遇到了一个问题,当应用程序启动时,spring boot加载了控制器中定义的所有映射。

    • 问题内容: 这是一个非常基本的问题-但我无法通过在线搜索找到答案。 我正在使用python控制ArcGIS,并且有一个简单的python脚本,该脚本调用了一些预先编写的代码。 但是,当我对预写代码进行更改时,它似乎没有导致任何更改。我导入了此模块,并尝试刷新它,但是没有任何反应。 我什至将它调用的文件移到了另一个位置,脚本仍然可以正常工作。昨天我做的一件事是我将所有python文件都添加到sys路