Spring+MyBatis使用 @Transactional 注解管理事务

@Transactional 是 Spring 框架提供的一个注解,用于声明一个方法或类需要在事务的上下文中执行。当使用 @Transactional 注解时,Spring 会为该方法或类创建一个代理,该代理会确保方法在执行时处于一个合适的事务边界内。

以下是 @Transactional 注解的一些关键特性和用法:

1. 声明位置

  • 可以声明在类级别上,这样该类中的所有公共方法都将使用相同的事务属性。
  • 可以声明在方法级别上,这样只有该方法会使用特定的事务属性。

2. 事务属性

  • propagation:定义事务的传播行为。例如,Propagation.REQUIRED 表示当前方法必须在事务上下文中运行;如果当前没有事务,就新建一个事务。
  • isolation:定义事务的隔离级别。例如,Isolation.READ_COMMITTED 意味着一个事务只能读取已经提交的数据。
  • timeout:定义事务的超时时间。
  • readOnly:标记事务为只读,以优化性能。
  • rollbackFor 和 noRollbackFor:定义哪些异常会导致事务回滚,以及哪些异常不会。

3. 使用示例

import org.springframework.transaction.annotation.Transactional;  
import org.springframework.stereotype.Service;  
  
@Service  
public class MyService {  
  
    @Transactional  
    public void methodWithTransactionalAnnotation() {  
        // ... 方法体 ...  
    }  
  
    @Transactional(propagation = Propagation.REQUIRES_NEW)  
    public void methodWithCustomPropagation() {  
        // ... 方法体 ...  
    }  
  
    @Transactional(readOnly = true)  
    public void readOnlyMethod() {  
        // ... 方法体 ...  
    }  
}

4. 注意事项

  • @Transactional 注解只能应用于 public 方法上。如果应用于非 public 方法上,Spring 不会创建代理,因此事务管理不会生效。
  • 当使用代理时,从同一个类中的另一个方法调用注解了 @Transactional 的方法,事务管理不会生效,因为这是在同一个对象内部调用,而不是通过代理调用。要解决这个问题,可以将需要事务管理的方法移到一个新的服务类中,并从那里调用。
  • 如果需要在事务中捕获异常并仍然希望事务回滚,应确保重新抛出运行时异常(RuntimeException)或其子类,因为 Spring 默认只在遇到运行时异常时回滚事务。

通过正确使用 @Transactional 注解,你可以确保数据库操作在正确的事务边界内执行,从而提高数据的一致性和可靠性。

在 Maven 的 pom.xml 文件中,为了使用 Spring 的 @Transactional 注解,你需要添加 Spring Framework 的相关依赖。@Transactional 注解是 Spring Framework 的一部分,因此你通常需要添加 Spring Context 的依赖,以及如果你正在使用 Spring Boot,则可能还需要 Spring Boot Starter 的依赖。

以下是一个基本的 Maven 依赖示例,展示了如何添加 Spring Context 的依赖:

	<dependencies>
		<!-- Spring 集成 mybatis -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.2.1.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.2.1.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>2.0.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-dbcp2</artifactId>
			<version>2.1.1</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.2</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.11</version>
		</dependency>
		<!-- 日志 log4j -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
	</dependencies>

需要为Spring提供配置文件:

<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/mvc 
       http://www.springframework.org/schema/mvc/spring-mvc.xsd 
       http://www.springframework.org/schema/tx  
       http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <context:component-scan base-package="com.sict"/>
    
   
    <!--配置数据源,连接数据库-->
    <bean class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" id="dataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=UTC&amp;useSSL=false"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    	<property name="dataSource" ref="dataSource"/>  
	</bean>
	
	<!-- 在Spring配置文件中启用声明式事务管理。使用<tx:annotation-driven />标签来启用对@Transactional注解的支持。-->
	<tx:annotation-driven transaction-manager="transactionManager" />
	
    
    <!--配置sql会话工厂-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="classpath:mybatis.xml"></property>
    </bean>
    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" id="mapperScannerConfigurer">
        <property name="basePackage" value="com.sict.model.dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>
</beans>

上面配置了数据源,.DataSourceTransactionManager 事务管理器,启用对@Transactional注解的支持。当然还有mybatis自己的配置文件classpath:mybatis.xml和mapper映射文件的位置。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sict.model.dao.PersonMapper;
import com.sict.model.vo.Person;
import java.util.List;

@Service
public class PersonService {
	
	@Autowired
	private PersonMapper mapper;
	
	public List<Person> showAll() {
		return mapper.selectAll();
	}

	@Transactional
	public int insertPerson() {
		Person p = new Person(10, "zxg", 20, "1234");
		int r = mapper.insertPerson(p);

		p = new Person(10, "zxg", 20, "12345678"); // 密码超长,引发异常
		r = mapper.insertPerson(p);

		return r;
	}

	@Transactional
	public int deletePerson() {
		int r = mapper.deletePerson(10);
		return r;
	}
}

上面insertPerson方法执行2条insert语句,要么都成功,要么都失败。

如果你正在使用 Spring Boot,那么通常会添加 Spring Boot Starter 的依赖,这些 Starter 依赖会自动包含 Spring 框架所需的多个依赖,包括 Spring Context。例如:

<dependencies>  
    <!-- Spring Boot Starter Data JPA, which includes support for @Transactional -->  
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-data-jpa</artifactId>  
        <version>YOUR_SPRING_BOOT_VERSION</version>  
    </dependency>  
      
    <!-- Database driver, for example, MySQL -->  
    <dependency>  
        <groupId>mysql</groupId>  
        <artifactId>mysql-connector-java</artifactId>  
        <version>YOUR_MYSQL_DRIVER_VERSION</version>  
    </dependency>  
      
    <!-- Other dependencies as needed -->  
</dependencies>

请将 YOUR_SPRING_BOOT_VERSION 替换为你想要使用的 Spring Boot 版本号。

使用 Spring Boot Starter 依赖时,通常不需要手动添加 Spring Context 或其他基础 Spring 框架的依赖,因为 Starter 会为你自动处理这些依赖关系。

请确保你使用的 Spring 或 Spring Boot 版本与你的项目其他部分兼容,并且符合你的项目需求。你可以访问 Spring 的官方网站或 Maven 中央仓库来查找最新的版本信息。

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

因上精进,果上随缘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值