Java 尝试同时保存到两个数据库时,当前线程找不到会话错误
嗨,我试图同时保存到两个数据库中,但总是出错Java 尝试同时保存到两个数据库时,当前线程找不到会话错误,java,spring,hibernate,jpa,transactions,Java,Spring,Hibernate,Jpa,Transactions,嗨,我试图同时保存到两个数据库中,但总是出错 Exception in thread "main" org.hibernate.HibernateException: No Session found for current thread 这是我的密码: @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW, readOnly=false) public void save(Arsena
Exception in thread "main" org.hibernate.HibernateException: No Session found for current thread
这是我的密码:
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW, readOnly=false)
public void save(ArsenalPlayer domain1, ArsenalPlayer2 domain2)
throws Exception {
dao1.save(domain1);
dao2.save(domain2);
}
- dao1使用连接到datasource1的sessionFactory
- dao2使用连接到datasource2的sessionFactory
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/arsenal" />
<property name="user" value="root" />
<property name="password" value="ahmids" />
</bean>
DAO2
<bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/arsenal2" />
<property name="user" value="root" />
<property name="password" value="ahmids" />
</bean>
<bean id="sessionFactory2"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource2" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">update</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.gongfu4.bean.ArsenalPlayer2</value>
</list>
</property>
</bean>
@Autowired
SessionFactory sessionFactory2;
public void save(ArsenalPlayer2 domain) {
sessionFactory2.getCurrentSession().merge(domain);
}
我的配置有问题吗?您当前的配置不支持全局事务(XA),因此无法在两个不同的数据库上跨一个事务 因此,您需要两个Hibernate事务管理器,每个会话工厂一个。然后,您需要指示事务服务应该使用哪个事务管理器 因此,不是:
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW, readOnly=false)
public void save(ArsenalPlayer domain1, ArsenalPlayer2 domain2)
throws Exception {
dao1.save(domain1);
dao2.save(domain2);
}
你应该:
<bean id="txManager1" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory1" />
</bean>
<bean id="txManager2" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory2" />
</bean>
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW, readOnly=false, value="txManager1")
public void save(ArsenalPlayer domain1)
throws Exception {
dao1.save(domain1);
}
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW, readOnly=false, value="txManager2")
public void save(ArsenalPlayer domain2)
throws Exception {
dao2.save(domain2);
}
@事务性(rollboor=Exception.class,propagation=propagation.REQUIRES_NEW,readOnly=false,value=“txManager1”)
公共无效保存(ArsenalPlayer域1)
抛出异常{
dao1.save(域1);
}
@事务性(rollboor=Exception.class,propagation=propagation.REQUIRES_NEW,readOnly=false,value=“txManager2”)
公共无效保存(ArsenalPlayer域2)
抛出异常{
dao2.save(域2);
}
您不能像那样使用这两个事务管理器。您有两个数据源、两个事务管理器,根据您的代码,我理解您希望在同一事务中执行两个保存操作。问题是“来自哪个事务管理器的事务?”
按照代码和配置的方式,Spring将使用“默认”事务管理器,因为默认情况下,
将搜索id为“transactionManager”的事务管理器bean,而具有此id的bean是用于数据源数据源的bean。但是您的代码不工作,这是预期的行为。Spring将使用sessionFactory
和dao1.save(domain1)打开一个Hibernate会话代码>调用将成功,因为这是正确数据源的正确Hibernate会话。但是当dao2.save时(domain2)调用code>方法时,您将从dao1
调用中获得相同的会话,但用于第二个数据库的db操作
在我看来,你有两个选择:
使用JTA事务管理器来协调这两个数据源。对于JTA,两个保存操作将是原子的。如果一个失败,那么两个都将回滚
在两个不同的事务中执行两个保存(域)
操作,正确配置@Transactional
注释以使用正确的事务管理器。在这种情况下,两个保存操作将不是原子的。如果一次保存失败,则只回滚该次保存。请参见以下Spring参考文档中的豁免:
...
...
使用openSession()而不是currentSession()导致异常的行在哪里?我有两个事务管理器,一个id=“transactionManager”,另一个id=“myTx”,每个事务都注入了difference sessionFactory,从您的回答来看,如果一个事务失败,它将回滚失败的事务,不是都是数据库,顺便说一句,对不起我的英语不好,如果你不使用JTA就会这样。JTA使全局事务能够跨越多个数据源。但是你需要一个JTA事务管理器,比如JEE应用服务器提供给你的那个,或者一个独立的事务管理器,比如Bitronix、Atomikos。是的,我想用一个事务方法保存到两个数据库,所以如果一个操作无法保存,两个数据库都将回滚,dao1保存操作没有任何问题,但是当它转到dao2时,我总是收到一个“找不到当前线程的会话”错误。很抱歉,我的英语不好,所以您需要使用选项1-使用JTA事务管理器。请看一篇使用Atomikos(JTA提供商)协调两个独立数据源的博客文章。请注意,您需要在配置中做很多更改:从数据源定义(需要是XA)开始,然后更改会话工厂,最后定义Atomikos配置。因此,我必须使用JTA事务来处理多个数据库。感谢您提供的信息和链接。我会接受你的回答。谢谢
@Autowired
SessionFactory sessionFactory2;
public void save(ArsenalPlayer2 domain) {
sessionFactory2.getCurrentSession().merge(domain);
}
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW, readOnly=false)
public void save(ArsenalPlayer domain1, ArsenalPlayer2 domain2)
throws Exception {
dao1.save(domain1);
dao2.save(domain2);
}
<bean id="txManager1" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory1" />
</bean>
<bean id="txManager2" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory2" />
</bean>
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW, readOnly=false, value="txManager1")
public void save(ArsenalPlayer domain1)
throws Exception {
dao1.save(domain1);
}
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW, readOnly=false, value="txManager2")
public void save(ArsenalPlayer domain2)
throws Exception {
dao2.save(domain2);
}
public class TransactionalService {
@Transactional("order")
public void setSomething(String name) { ... }
@Transactional("account")
public void doSomething() { ... }
}
<tx:annotation-driven/>
<bean id="transactionManager1" class="org.springframework.jdbc.DataSourceTransactionManager">
...
<qualifier value="order"/>
</bean>
<bean id="transactionManager2" class="org.springframework.jdbc.DataSourceTransactionManager">
...
<qualifier value="account"/>
</bean>