基于注解的Spring事务配置

spring采用@Transactional注解进行事务申明,@Transactional既可以在方法上申明,也可以在类上申明,方法申明优先于类申明。

1、pom配置

包括spring核心包引入以及spring jdbc包引入。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.coshaho</groupId>
  <artifactId>coshaho-model</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>coshaho-model</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
  
      <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.1.4.RELEASE</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.4.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.1.4.RELEASE</version>
    </dependency>
      
      <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.13</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>
  
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

2、spring.xml配置

需要引入tx标签,初始化DataSourceTransactionManager实例,并把@Transactional和DataSourceTransactionManager实例关联起来。

<?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"
       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"
       >
    
    <!-- 注解注入 -->
    <context:component-scan base-package="com.coshaho.*" />
    
    <!-- 引入jdbc配置文件 -->   
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!-- 使用spring初始化DataSource -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!-- 使用JdbcTemplate封装DataSource -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 定义事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!--使用注释事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

3、测试代码

定义数据库表对象以及映射关系

package com.coshaho.vo;

public class User 
{
    private int id;
    private String name;
    private int age;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
    }
}
package com.coshaho.dao;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

import com.coshaho.vo.User;

public class UserMapper implements RowMapper<User>
{
    public User mapRow(ResultSet rs, int rowNum) throws SQLException 
    {
        User user = new User();
        user.setId(rs.getInt("id"));
        user.setName(rs.getString("name"));
        user.setAge(rs.getInt("age"));
        return user;
    }
}

我们定义user表字段name为唯一字段,用事务代码插入两行相同记录,看看能否成功。

package com.coshaho.dao;

import com.coshaho.vo.User;

public interface UserDao 
{
    public void create(String name, int age);
    public User query(int id);
    public void create2User();
}
package com.coshaho.dao;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.coshaho.vo.User;

@Component
public class UserDaoImpl implements UserDao
{
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Transactional
    public void create(String name, int age) 
    {
        jdbcTemplate.update("insert into user(name, age) values (?, ?)", 
                name, age);
    }

    public User query(int id) 
    {
        List<User> user = jdbcTemplate.query("select * from user where id=" + id, 
                new UserMapper());
        return user.get(0);
    }
    
    @Transactional
    public void create2User()
    {
        create("b", 1);
        create("b", 1);
    }
    
    private static ApplicationContext context;
    public static void main(String[] args)
    {
        String xmlpath = "spring.xml";
        context = new ClassPathXmlApplicationContext(xmlpath);
        UserDao userDao = (UserDao) context.getBean("userDaoImpl");
        userDao.create("a", 1);
        userDao.create2User();
    }
}

执行结果

可以看到,在同一个事务中依次插入两条相同记录,都没有插入成功。

posted @ 2019-03-02 11:14  coshaho  阅读(3681)  评论(0编辑  收藏  举报