Spring 事务基础练习

来源:互联网 发布:佳能照片打印机软件 编辑:程序博客网 时间:2024/06/06 02:56

在Spring框架中,基于注解(Annotation)方式实现对事务控制练习

  • 利用Eclipse创建一个Maven项目,目录结构如下:
    这里写图片描述

  • 在项目的 pom.xml 文件中引入以下依赖库(Spring版本号采用:4.3.10.RELEASE)

    • spring-core
    • spring-jdbc
    • spring-context
    • mysql-connector-java
  • 在 src/main/resource目录下新建 schema.sql,用于建表

CREATE TABLE IF NOT EXISTS `student` (    `id` int (      11    ) NOT NULL AUTO_INCREMENT ,    `studentName` varchar (45) DEFAULT NULL,    PRIMARY KEY (`id`)  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE IF NOT EXISTS `student_score` (    `id` int (      11    ) NOT NULL AUTO_INCREMENT ,    `student_id` int (11) DEFAULT NULL,    `subject` varchar (45) DEFAULT NULL,    `score` int (11) DEFAULT NULL,    PRIMARY KEY (`id`),    KEY `fk_stuname_idx` (      `student_id`    ),    CONSTRAINT `fk_stuname` FOREIGN KEY (`student_id`) REFERENCES `student` (      `id`    )      ON DELETE NO ACTION          ON UPDATE            NO ACTION          )ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 启动MySQL Server,创建数据库,名称:qsx_school

  • 在src/main/resource目录下编写applicationContext.xml

<?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:jdbc="http://www.springframework.org/schema/jdbc"; xmlns:tx="http://www.springframework.org/schema/tx";      xmlns:aop="http://www.springframework.org/schema/aop";      xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/jdbchttp://www.springframework.org/schema/jdbc/spring-jdbc.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd";>      <!-- 配置扫描注解定义Bean的目录,即只有定义在以下目录中(或子目录)中的Bean类才能Spring IOC容器感知到 -->      <context:component-scan base-package="online.qingshixun.project"></context:component-scan>      <!-- 定义数据源 -->      <bean id="dataSource"            class="org.springframework.jdbc.datasource.DriverManagerDataSource">            <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>            <property name="url" value="jdbc:mysql://localhost:3306/qsx_school"></property>            <property name="username" value="root"></property>            <property name="password" value="root"></property>      </bean>      <!-- 使spring检查 @Transactional 注解,配置此元素 @Transactional注解生效 -->      <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>      <!-- 声明事务管理 -->      <bean id="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">            <property name="dataSource">                  <ref bean="dataSource" />            </property>      </bean>      <!-- 应用启动时,利用 schema.sql 脚本自动初始化数据表结构 -->      <jdbc:initialize-database data-source="dataSource">            <jdbc:script location="classpath:schema.sql" />      </jdbc:initialize-database></beans>
  • 编写学生注册数据存取类StudentDao
package online.qingshixun.project.dao;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import javax.sql.DataSource;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.datasource.DataSourceUtils;import org.springframework.stereotype.Repository;@Repositorypublic class StudentDao {    @Autowired    private  DataSource dataSource;    @SuppressWarnings("unused")    private Connection getConnection() {        // 根据数据源获取连接        Connection connection = DataSourceUtils.getConnection(dataSource);        return connection;    }    /**     * 保存学生信息     *      * @param userName     * @return     * @throws SQLException     */    public int addStudent(String userName) throws SQLException{        // 利用JDBC保存学生基本信息,学生属性参考 schema.sql 中定义        Connection con = this.getConnection();        String sql = "INSERT INTO student(studentName) VALUES(?);";        java.sql.PreparedStatement preparedStatement = con.prepareStatement(sql);        preparedStatement.setString(1, userName);        preparedStatement.executeUpdate();        //返回主键        String sql1 = "select id from student where studentName = ?";        java.sql.PreparedStatement preparedStatement2 = con.prepareStatement(sql1);        preparedStatement2.setString(1, userName);        ResultSet result1 =  preparedStatement2.executeQuery();        int resultid = 0;        while(result1.next()) {            resultid = result1.getInt(1);            System.out.println("re="+resultid);        }        return resultid;    }    /**     * 保存学生成绩信息     *      * @param studentId     * @throws SQLException     */    public void addStudentScore(int studentId) throws SQLException {        // 利用JDBC保存学生关联的成绩信息        Connection con = this.getConnection();        String sql = "INSERT INTO student_score(student_id,subject,score) VALUES(?,?,98);";        java.sql.PreparedStatement preparedStatement = con.prepareStatement(sql);        preparedStatement.setInt(1, studentId);        preparedStatement.setString(2, "Computer");        preparedStatement.executeUpdate();        // 模拟抛出异常,在这里抛出运行时异常则本次操作插入的学生表(student)与成绩表(student_score)都会回滚(rollback)        throw new RuntimeException();    }}
  • 编写学生注册服务类 StudentService,利用注解实现事务控制
package online.qingshixun.project.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import online.qingshixun.project.dao.StudentDao;@Servicepublic class StudentService {    // 注入 StudentDao    @Autowired    private StudentDao studentDao;    /**     * 保存学生     *      * @param userName     * @throws Exception     */    @Transactional(transactionManager="txManager",propagation=Propagation.REQUIRES_NEW,rollbackFor=Exception.class)    public void addStudent(String userName) throws Exception {        // 保存学生信息        int studentId = studentDao.addStudent(userName);        // 保存学生关联的成绩信息        studentDao.addStudentScore(studentId);    }}
  • 编写测试类 SpringTest
package online.qingshixun.project.test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.stereotype.Component;import online.qingshixun.project.service.StudentService;@Componentpublic class SpringTest {    @Autowired    private StudentService studentService;    public static void main(String[] args) throws Exception {        // 初始化 applicationContext        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");        // SpringIoCTest 实例必须通过 IOC容器获得,否则不能类中使用 @Autowired 方式注入其它 Bean        SpringTest iocTest = ctx.getBean(SpringTest.class);        iocTest.testAddSstudent();        // 关闭 ApplicationContext        ((ClassPathXmlApplicationContext) ctx).close();    }    public void testAddSstudent() throws Exception {        // 添加和保存学生,学生名称:实训        studentService.addStudent("实训");    }}
  • 在Eclipse运行SpringTest测试类:

    1. 首先注释掉StudentDao类中的addStudentSore方法中的 throw new RuntimeException(); 代码,运行SpringTest后,qsx_school数据库中的student,student_score表中将个插入一条数据
    2. 然后取消注释StudentDao类中的addStudentSore方法中的 throw new RuntimeException(); 代码,运行SpringTest后,报错:java.lang.RuntimeException,且qsx_school数据库中的student,student_score表中将不插入任何数据