月夜之影 2019-08-26 14:50 采纳率: 0%
浏览 539

spring+hibernate+atomikos 实现JTA分布式事务时自定义事务隔离级别无效

            因为需要对两个数据库同时操作并且放在同一个事务中,所以采用了atomikos去实现JTA分布式事务。数据库用的是SQL Server2014 . 

            现在的问题是,事务提交回滚,一切都正常,但是没有按照设定好的事务隔离级别给数据库表加锁。比如service中的save方法 设定的是SERIALIZABLE隔离级别,测试时查询数据库表隔离级别,并未按照预期加锁。
            以下是配置文件,请大神给解惑一下。
<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans             
        http://www.springframework.org/schema/beans/spring-beans.xsd             
        http://www.springframework.org/schema/context            
        http://www.springframework.org/schema/context/spring-context.xsd             
        http://www.springframework.org/schema/tx             
        http://www.springframework.org/schema/tx/spring-tx.xsd          
        http://www.springframework.org/schema/aop            
        http://www.springframework.org/schema/aop/spring-aop.xsd 
        http://www.springframework.org/schema/mvc  
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

    <!-- 修改 -->
    <!-- 1.扫描包 -->
    <!--context:component-scan base-package=""></context:component-scan-->

    <!--context:component-scan base-package="wms.*">     
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>     
    </context:component-scan-->   

    <context:component-scan base-package="com.baoJian.wmsBasic.*.dao">     
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>     
    </context:component-scan>         
    <context:component-scan base-package="com.baoJian.wmsBasic.*.service">     
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>     
    </context:component-scan>       

    <!-- 2.加载属性文件 -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"></property>
    </bean>
    <!--develop开发环境配置,测试环境配置 对应web.xml中也有相关设置-->
    <!--beans profile="develop">  
        <context:property-placeholder location="classpath:jdbc.properties"/>  
    </beans> 
    <beans profile="product">  
        <context:property-placeholder location="classpath:jdbc_product.properties"/>  
    </beans-->  

    <beans>     
    <!-- 修改 -->
    <!-- 3.配置数据库连接池 更改为JTA-->
    <bean class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" id="dataSource">  
        <!-- Set unique name for this DataSource -->    
        <property name="uniqueResourceName"><value>dataSource_main</value></property>  
        <!-- Set XADatasource class name -->    
        <property name="xaDataSourceClassName" value="com.microsoft.sqlserver.jdbc.SQLServerXADataSource" />  

        <property name="xaProperties">  
           <props>  
               <prop key="URL">${jdbcUrl}</prop>               
           </props>  
        </property>   
        <!-- set properties for datasource connection pool -->    
        <property name="poolSize" value="3" />  
        <!-- timeout after 20000 seconds -->  
        <property name="minPoolSize" value="3" />
        <property name="maxPoolSize" value="6" />
        <property name="borrowConnectionTimeout" value="60" />    
        <property name="reapTimeout"><value>300</value></property>   

        <property name="loginTimeout" value="40" /> 
        <property name="testQuery"> 
            <value>select 1</value> 
        </property>  
    </bean>  

    <bean class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" id="dataSource_erp">  
        <!-- Set unique name for this DataSource -->    
        <property name="uniqueResourceName"><value>dataSource_erp</value></property>  
        <!-- Set XADatasource class name -->    
        <property name="xaDataSourceClassName" value="oracle.jdbc.xa.client.OracleXADataSource" />  
        <property name="xaProperties">  
            <props>  
                <!--prop key="URL">jdbc:oracle:thin:@erptest.baojian.com:1541:DEV2</prop--> 
                <prop key="URL">${oraJdbcUrl}</prop>   
                <prop key="user">${oraUser}</prop>
                <prop key="password">${oraPassword}</prop>
           </props>  
        </property>   
        <!-- set properties for datasource connection pool -->    
        <property name="poolSize" value="3" />  
        <!-- timeout after 20000 seconds -->  
        <property name="reapTimeout"><value>300</value></property>    
    </bean>        

    <!-- 修改 -->
    <!-- 4.Hibernate的相关信息 -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
    </bean>

    <bean id="sessionFactory_erp" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource_erp"></property>
        <property name="configLocation" value="classpath:hibernate_erp.cfg.xml"/>
    </bean>


    <!-- 分布式事务 -->
    <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
        <property name="forceShutdown" value="true"/>
    </bean>
    <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
        <property name="transactionTimeout" value="50000"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="atomikosTransactionManager"/>
        <property name="userTransaction" ref="atomikosUserTransaction"/>
        <property name="allowCustomIsolationLevels" value="true"/>
    </bean>   

    <!--<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean> -->

    <!-- 6.开启事务注解 -->
    <!--tx:annotation-driven transaction-manager="transactionManager"/-->

    <tx:advice id="txAdvice" transaction-manager="transactionManager" >
        <tx:attributes>
            <!--init初始化操作  calculate计算类操作 save保存操作 remove删除操作 update更新操作-->
            <tx:method name="init*" propagation="REQUIRED" rollback-for="Exception"></tx:method> 
            <tx:method name="calculate*" propagation="REQUIRED" rollback-for="Exception"></tx:method> 
            <tx:method name="save*" propagation="REQUIRED" isolation="SERIALIZABLE" rollback-for="Exception"></tx:method>   
            <tx:method name="*" read-only="true"></tx:method> 
        </tx:attributes>
    </tx:advice>

    <!--定义哪些类的哪些方法参与事务 -->
    <aop:config>
        <!-- <aop:pointcut id="allManagerMethod" expression="execution(* com.baojian.demo.service.*.*(..))"/> -->
        <aop:pointcut id="allServiceMethod" expression="execution(* *..service.*.*(..))"/>
        <aop:advisor pointcut-ref="allServiceMethod" advice-ref="txAdvice"/>
    </aop:config>

</beans>

测试例子

server中的一个方法

    public void saveTestHeader() throws InventoryServiceException, ReceiptServiceException
    {
        System.out.println("------------------TransactionSynchronizationManager"+TransactionSynchronizationManager.getCurrentTransactionIsolationLevel());


        //查询并锁定
        TestHeader testHeader = this.testDao.findOneByHQL("from TestHeader where id=160");
        Thread.sleep(30000);
    }
  • 写回答

1条回答 默认 最新

  • 明初啥都能学会 2024-04-27 11:18
    关注

    你的配置文件中,事务的隔离级别设置似乎是正确的,但是有几个可能导致事务隔离级别无效的原因:

    1. 数据库支持问题:检查一下你所使用的数据库是否支持设置SERIALIZABLE隔离级别。虽然SQL Server支持SERIALIZABLE隔离级别,但是在某些情况下可能会因为其他因素而无法生效。你可以尝试在数据库端手动执行SQL语句设置隔离级别,观察是否生效。

    2. Atomikos配置:检查一下Atomikos的配置,确保它能够正确地管理分布式事务,并且将事务隔离级别传递给数据库。

    3. Hibernate配置:确保Hibernate的配置文件中也设置了事务隔离级别。你可以在Hibernate配置文件中添加如下配置:

      <property name="hibernate.connection.isolation">SERIALIZABLE</property>
      
    4. 事务方法是否被代理:确保你的事务注解被正确地应用在需要事务管理的方法上,并且这些方法是通过Spring的AOP进行代理的。

    另外,你可以尝试在服务方法中手动设置隔离级别,而不是通过配置文件。例如:

    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void saveTestHeader() throws InventoryServiceException, ReceiptServiceException {
        // 查询并锁定
        TestHeader testHeader = this.testDao.findOneByHQL("from TestHeader where id=160");
        Thread.sleep(30000);
    }
    

    最后,记得检查数据库的日志,查看是否有相关的错误或警告信息,以确定事务隔离级别是否被正确应用。

    评论

报告相同问题?

悬赏问题

  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵