【Spring 事务管理系列之一】Spring使用JDBC的事务管理例子

    本打算系列之一把此次写的大纲列出来呢,无奈本身没想好,只有大体定一个方向,待后面补充,或者从新组织这一系列。
java

作几个概念的澄清和一些基础东西的介绍node

一、假设你熟悉JDBC提供的api操做,好比:mysql

    JDBC提供的事务处理API很是少,请不要被Spring中事务处理的那一堆源代码所打击得信心尽失,这些框架提供的事务处理功能归根结底主要经过以Connection类的方法完成:spring

Connection.setAutoCommit(boolean);
Connection.commit();
Connection.rollback();

二、本地事务和分布式事务sql

    本地(Local Transaction)事务指只有一个数据源参与的事务,好比只有数据库或者只有JMS;分布式事务(Distributed Transaction)指有多个数据源同时参与的事务,好比一项操做须要同时访问数据库和经过JMS发送消息,或者一项操做须要同时访问两个不一样数据库。对于分布式事务,Java提供了JTA规范,它的原理与本地事务存在不一样。 鉴于多数状况下Java事务为本地事务。数据库

三、线程安全的基础api

    为何会扯到线程安全呢,由于一次DB的链接是Connection对象决定的,同一个Connection对象,有可能会同事被多个Thread访问,同时了解ThreadLocal【1】来解决多线程之间的共享问题。
安全

四、Spring 事务管理系列之一(JDBC的事务管理例子)多线程

    这个是开篇,经过这个系列一,会直观的展现一下事务,给刚接触的同窗一点直观的感知,固然可能有本身理解不当的地方,也请大牛指出。框架

    本文将使用两张表来演示事务的处理过程,怎么来证实事务在执行了呢?通常状况下是save以后数据库db能看获得,可是这不能证实事务起做用了,这个例子中会经过使用插入一张customer表,一张Address表,在插入customer表以后,抛出异常,在插入address表,这两个操做是放在一个事务里面的,若是最后表里面没有数据,则代表,事务确实起做用啦,要么全插,要么不插。

    4.一、建立database

customer.sql

CREATE TABLE `Customer` (
  `id` int(11) unsigned NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

address.sql

CREATE TABLE `Address` (
  `id` int(11) unsigned NOT NULL,
  `address` varchar(20) DEFAULT NULL,
  `country` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

数据库表结构:

  

4.二、项目使用maven进行管理,因为本项目使用jdbc链接mysql,因此包含mysql-connector-java,spring-tx,由于要实用JDBCTemplate因此又包括spring-jdbc其余依赖以下:

<properties>

		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Spring -->
		<spring-framework.version>3.0.6.RELEASE</spring-framework.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

		<!-- Test -->
		<junit.version>4.11</junit.version>

	</properties>

	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
                <dependency>
                  <groupId>cglib</groupId>
                  <artifactId>cglib-nodep</artifactId>
                  <version>3.1</version>
                </dependency>
		<!-- Spring JDBC and MySQL Driver -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.0.5</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Test Artifacts -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring-framework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>

	</dependencies>

4.三、具体实现

    关于spring.xml bean的配置,还有pojo的配置很少作介绍。主要提出来事务处理的逻辑:

public void create(Customer customer) {
		String queryCustomer = "insert into Customer (id, name) values (?,?)";
		String queryAddress = "insert into Address (id, address,country) values (?,?,?)";

		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

		jdbcTemplate.update(queryCustomer, new Object[] { customer.getId(),
				customer.getName() });
		System.out.println("Inserted into Customer Table Successfully");
		jdbcTemplate.update(queryAddress, new Object[] { customer.getId(),
				customer.getAddress().getAddress(),
				customer.getAddress().getCountry() });
		System.out.println("Inserted into Address Table Successfully");
	}

可见,customer表插入以后,打印“Inserted into Customer Table Successfully”而后再插入Address那张表,咱们在设计Address这张表的时候要求Address的地址字段是小于20 chars的长度,咱们在测试代码里面故意构造,大于20的长度,让其抛出异常,代码以下:

Customer customer = new Customer();
		customer.setId(2);
		customer.setName("lianzi");
		Address address = new Address();
		address.setId(2);
		address.setCountry("china");
		// setting value more than 20 chars, so that SQLException occurs
		address.setAddress("********************************************");
		customer.setAddress(address);
		return customer;

运行结果:

同时查看,数据库发现customer表中,并没有数据,符合预期,代表事务生效啦。

五、问题和思考?

spring是如何实现事务管理的呢?下面几篇文章,会实现一个很简单的相似spring事务管理的功能。

代码下载

相关文章
相关标签/搜索