Spring实战学习笔记整理(5)-事务

事务概念

例:我的账户 -500,小红的账户 +500:要么都成功,要么都失败

  • 数据库的事务问题:对多条数据进行读写、并发访问导致的
  • 1.原子性:要么都成功,要么都失败
  • 2.一致性:数值上保持一致
  • 3.隔离性:2000-500=1500;2000+500=2500 1500 数据操作的过程中不允许其他再访问
  • 4.持久性:对数据的操作后要持久保存

举例:

  • INSERT INTO t_user (email,nickname,PASSWORD) VALUES (‘xxxx’,‘sss’,‘xxxxx’); – 1条数据:插入成功|插入失败
  • INSERT INTO t_user (email,nickname,PASSWORD) VALUES (‘xxxx’,‘sss’,‘xxxxx’); – 2条都插入成功 | 2条都没有插入失败 | 1条插入成功,1条没插入失败

代码实现

演示数据库连接
1.数据库连接池
1.1使用驱动获取连接的弊端
1.2如何配置连接池
1.3使用连接池实现数据库操作
2.JdbcTemplate
2.1传统方式进行数据库操作
2.2使用JdbcTemplate进行数据库操作:增删改查
3.集成声明式事务
3.1实现步骤
3.1.1引入jar包
3.1.2配置数据库连接池
3.1.3配置配置事务管理器
3.1.4开始事务注解扫描
3.2测试事务

student表

创建表student,添加表中信息及数据信息,效果如图所示:
Spring实战学习笔记整理(5)-事务_第1张图片

引入jar包

效果如图所示:
Spring实战学习笔记整理(5)-事务_第2张图片

part1:

Demo.java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.Map.Entry;
import javax.naming.spi.DirStateFactory.Result;
import javax.swing.Spring;
import javax.swing.plaf.synth.SynthGraphicsUtils;
import javax.xml.crypto.Data;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
/**
 * 演示数据库链接
 * @author Katrina
 *
 */
public class Demo {
	
	@Test
	public void test1() throws Exception {
		//1.加载驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2.获取链接
		String url = "jdbc:mysql://localhost:3306/demo?charactorEncoding=UTF-8";
		String user = "root";
		String password = "1234"; //"" 和 " "不同!
		Connection connection = DriverManager.getConnection(url, user, password);
		//3.创建statement并执行sql
		Statement statement = connection.createStatement();
		String sql = "INSERT INTO student (name) VALUES ('tom')";
		int row = statement.executeUpdate(sql);
		//4.处理结果集
		System.out.println("执行sql影响行数是:" + row);
		//5.关闭资源
		statement.close();
		connection.close();
	}
	
	@Test
	public void test2() throws Exception {
		//1.加载驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2.获取链接  //高版本驱动,必须添加的参数serverTimezone=Asia/Shanghai&useSSL=false
		String url = "jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai&useSSL=false";
		String user = "root";
		String password = "1234"; //"" 和 " "不同!
		Connection connection = DriverManager.getConnection(url, user, password);
		//3.创建statement并执行sql
		Statement statement = connection.createStatement();
		String sql = "INSERT INTO student (name) VALUES ('tom')";
		int row = statement.executeUpdate(sql);
		//4.处理结果集
		System.out.println("执行sql影响行数是:" + row);
		//5.关闭资源
		statement.close();
		connection.close();
	}
	
	@Test
	public void test3() throws Exception {
		//数据库连接池
		DruidDataSource druidDataSource = new DruidDataSource();
		druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
		druidDataSource.setUrl("jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai&useSSL=false");
		druidDataSource.setUsername("root");
		druidDataSource.setPassword("1234");
		//获取链接
		DruidPooledConnection connection = druidDataSource.getConnection();
		//创建statement、执行sql
		Statement statement = connection.createStatement();
		String sql = "INSERT INTO student (name) VALUES ('tom1')";
		int row = statement.executeUpdate(sql);
		//处理结果集
		System.out.println("执行sql影响行数是:" + row);
		//关闭资源
		statement.close();
		connection.close();
		druidDataSource.close(); //真正关闭资源
	}

	@Test
	public void test4() throws Exception {
		//1.创建容器
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
		//2.获取类并执行操作
		DruidDataSource dataSource = (DruidDataSource) context.getBean("dataSource");
		DruidPooledConnection connection = dataSource.getConnection();
		Statement statement = connection.createStatement();
		String sql = "INSERT INTO student (name) VALUES ('tom22')";
		int row = statement.executeUpdate(sql);
		
		System.out.println("sql执行影响的行数:" + row);
		
		//3.关闭容器
		statement.close();
		connection.close();
		dataSource.close();
		context.close();
	}
	
	@Test
	public void test5() {
		//1.创建容器
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
		//2.获取类并操作
		JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
		/*
		 * jdbcTemplate的增删改查
		 * 查询:query*
		 * 修改:
		 * 		update*:返回值是int,对于数据的操作语句建议使用update
		 * 		execute:返回值是void,对于表结构等操作语句建议使用execute
		 */
		
//		jdbcTemplate.queryForList(sql); //查询列表
//		jdbcTemplate.queryForMap(sql); //查询单条数据
//		jdbcTemplate.queryForObject(); //查询单挑数据,必须查询出数据,没有回报错
//		jdbcTemplate.queryForRowSet(sql); //对应ResultSet存在
		
		String sql = "SELECT * FROM student WHERE id = 1";
		//												泛型
		Student student = jdbcTemplate.queryForObject(sql, new RowMapper<Student>() { //映射:匿名内部类,即实现接口

			@Override
			public Student mapRow(ResultSet resultSet, int arg1) throws SQLException {
				Student student = new Student();
				student.setId(resultSet.getInt("id"));
				student.setName(resultSet.getString("name"));
				return student;
			}
			
		});
		System.out.println("学生的id是:" + student.getId() + ",学生的名字是:" + student.getName());
		
//		String sql="SELECT * FROM student WHERE id=?";
//		Map data = jdbcTemplate.queryForMap(sql, 1);
		
		//不建议使用select *,效率比较差
//		String sql = "SELECT * FROM student WHERE id=1";
//		Map data = jdbcTemplate.queryForMap(sql);
//		for (Entry entry : data.entrySet()) {
//			System.out.println("key为:" + entry.getKey() + ",value值为:" + entry.getValue());
//		}
		
//		String sql = "INSERT INTO student (name) VALUES ('jack')"; 
//		int row = jdbcTemplate.update(sql);
//		System.out.println("执行sql影响的行数是:" + row);
		//3.关闭容器
		context.close();
	}
	
	@Test
	public void test6() {
		//1.加载驱动
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//2.获取链接
		String url = "jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai&useSSL=false";
		String user = "root";
		String password = "1234"; //"" 和 " "不同!
		Connection connection = null;
		try {
			connection = DriverManager.getConnection(url, user, password);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//3.创建statement并执行sql
		Statement statement = null;
		try {
			statement = connection.createStatement();
		} catch (SQLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		String sql = "INSERT INTO student (name) VALUES ('tom')";
		int row = 0;
		try {
			row = statement.executeUpdate(sql);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//4.处理结果集
		System.out.println("执行sql影响行数是:" + row);
		//5.关闭资源
		try {
			statement.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			connection.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

效果图:

测试test2,效果如图所示:
在这里插入图片描述
测试test3,效果如图所示:
在这里插入图片描述
测试test4,效果如图所示:
在这里插入图片描述
测试test5,效果如图所示:
在这里插入图片描述
测试test6,效果如图所示:
在这里插入图片描述

part2:

Student.java

/**
 * student实体类,用于映射数据库student表
 * @author Katrina
 *
 */
public class Student {

	private int id;
	private String name;
	
	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;
	}
	
}

StudentDao.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
/**
 * 使用dao,来模拟service
 * @author Katrina
 *
 */
//注解到类上,对类中所有的方法都进行事务管理
@Transactional(readOnly = true) //只读
@Repository
public class StudentDao {
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	/**
	 * 保存学生
	 */
	@Transactional(readOnly = false) //其他功能仍有..
	public void saveStudent() {
		String sql1 = "INSERT INTO student (NAME) VALUES ('james')";
		jdbcTemplate.update(sql1);
		
//		Integer.parseInt("xxxxxx");
		
		String sql2 = "INSERT INTO student (NAME) VALUES ('tom')";
		jdbcTemplate.update(sql2);
	}
	
}

StudentDaoTest.java

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * 事务测试类
 * @author Katrina
 *
 */
public class StudentDaoTest {

	@Test
	public void test() {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
		
		StudentDao studentDao = context.getBean(StudentDao.class);
		studentDao.saveStudent();
		
		context.close();
	}	
	
}

config.xml


<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-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

	
	
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver">property>
		<property name="url" value="jdbc:mysql://localhost:3306/demo?charactorEncoding=UTF-8">property>
		<property name="username" value="root">property>
		<property name="password" value="1234">property>
	bean>

	
	<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">property>
	bean>
	
	
	<context:component-scan base-package="demo">context:component-scan>
	
	
	<tx:annotation-driven transaction-manager="transactionManager"/>
beans>

效果图:

Spring实战学习笔记整理(5)-事务_第3张图片

你可能感兴趣的:(Spring实战)