Java Spring和Hibernate:多连接,线程安全

Java Spring和Hibernate:多连接,线程安全,java,sql,spring,hibernate,thread-safety,Java,Sql,Spring,Hibernate,Thread Safety,我有一个现有的项目运行良好,但现在我必须实现一个备份系统,该系统在exery-day执行,并将数据库转储到一个文件中。我想用一个ScheduledTask来解决这个问题,但这意味着还有另一个线程使用Hibernate 我的问题:如何使Hibernate线程安全 我有以下代码-(片段): 在applicationContext.xml中 <bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityMa

我有一个现有的项目运行良好,但现在我必须实现一个备份系统,该系统在exery-day执行,并将数据库转储到一个文件中。我想用一个
ScheduledTask
来解决这个问题,但这意味着还有另一个
线程使用Hibernate

我的问题:如何使Hibernate线程安全

我有以下代码-(片段):

在applicationContext.xml中

<bean id="myEmf"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dbDataSource" />
    <property name="packagesToScan" value="redb.main.core.model" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">validate</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop>
            <!-- <prop key="hibernate.enable_lazy_load_no_trans">true</prop> -->
        </props>
    </property>
</bean>

<!-- Transaction Management -->
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="myEmf" />
</bean>

<bean id="persistenceExceptionTranslationPostProcessor"
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
但是如果我理解正确的话,每个
线程
都需要它自己的
EntityManager
来自
EntityManager工厂

如何在其他类中创建新的
EntityManager


我没有
persistence.xml
。我必须创建它吗?

呵呵。欢迎来到地狱

主要的问题是,spring试图通过基于方面的解决方案来实现这一点。虽然这是有缺陷的(或不可调试的),但在一些琐碎的情况下它可以工作

对您的问题的一般回答是,
EntityManagerFactory
可以是您软件中的全局静态对象,尽管如果我只是简单地使用它,我会大吃一惊

默认情况下,SpringAOP在部署时“编织”应用程序,通过注释查找所有数据库实体类,并包装其方法以始终提供现有的entitymanager。这就是理论。但事实并非如此

实际上,你几乎无法控制到底会发生什么

我所做的:有一个名为
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter的servlet过滤器,它可以为每个请求打开一个entitymanager,并根据需要刷新/关闭它。是的,它的名字是关于“视图”,但很快它的名字就成了它的第一个bug:实际上我们不得不称它为“requesttransactionfilter”之类的。它与MVC视图无关,它正在处理来自servlet容器的http请求实体

如果您不喜欢在spring应用程序中使用servlet过滤器,还有一个名为
OpenEntityManagerViewInterceptor
的spring拦截器,其功能也非常类似

通过编程,您可以通过
createEntityManager()
方法从
EntityManager工厂
生成
EntityManager


快乐的谷歌搜索!您正处于漫长道路的开端。

Spring确保您有一个线程安全的
EntityManager
它只是一个代理,可以查找线程绑定的
EntityManager
或使用
EntityManager工厂创建一个新的。这一点也不可怕,见鬼,它可以在全球无数的企业应用程序中运行。不涉及编织,也不涉及AspectJ。唯一的AOP部分是,您需要确保事务中的所有内容都执行并正常工作。这不是一个漫长的过程,只是一个让您的配置正确的问题,从您描述的您没有并试图解决它。
OpenEntityManagerInViewInterceptor
实际上与视图无关,而是与请求和处理线程有关。但是对于后台线程来说,它没有任何作用。它是一个
HandlerInterceptor
,是SpringMVC的一部分,因此与web绑定。它对于后台线程是无用的。@M.Deinum好的。对于图书馆来说,给类起误导性的名字是一个次要的问题还是一个严重的问题?如果有些东西根本不起作用(例如,典型的问题:事务/实体管理器不是以某种方式创建的),你他妈的怎么能找出必须做什么?spring/aop中根本不存在本地责任的范例。几个月以来,我一直在挖掘spring源代码,并创建了大量关于它的问题,这些问题并没有简单地得到回答。是的,因为没有。对于令人不快的spring/aop问题,真正的答案是:“深入挖掘源头并祈祷”。这一回答有一定道理。如果Spring为您创建了一个存储库,然后您将其交给一个与Spring无关的线程,那么您就有麻烦了。这样做不是个好主意。但我做到了。最后对我起作用的是删除所有@Transactional注释,切换到手动事务(TransactionTemplate),重要的是,在每个TransactionTemplate上同步[Java synchronize()]。Spring将注入一个线程绑定的
EntityManger
(如文档中所述)。只要确保您所做的是在事务内部,这样就会有一个线程绑定的
EntityManager
。每个线程都有自己的线程(在事务或请求期间,如果使用
OpenEntityManagerInViewFilter/-Interceptor
,则不会得到一个单独的线程,但此处不适用,因为您希望使用后台线程)。但是,让数据库执行备份而不是尝试将其外部化不是更容易吗?如果事务没有启动(并且假设您有
@Transactional
),请确保您有一个
来启用事务。还要确保您没有复制bean实例,在
ContextLoaderListener
DispatcherServlet
中进行
组件扫描
可能会导致(取决于设置)复制bean,其中一个被代理并具有事务,而另一个没有事务。在过滤器中不应该有一个事务(还没有),因为它在执行所有其他事务之前执行,过滤器不会启动一个事务,而是将一个
EntityManager
绑定到当前线程。
@PersistenceContext
protected EntityManager entityManager;