JDBC中对事务的支持

事务的管理原则

  • 原子性:
  • 一致性:
  • 隔离性:


JDBC中对事物的支持

JDBC默认是每执行一条 sql 语句都会提交事务。

这对于批处理数据来说性能开销过大。而且不满足事务本该管理的原则-上述三点


1:阻止事务自动提交

     conn.setAutoCommit(false); // 不自动提交

2: conn.commit(); // 提交事务

3:conn.rollback();//回滚 



批处理 sql

Statement的一个方法addBatch(String sql)方法。

该方法了几将给定的sql存入Statement的命令列表中缓存。

当执行executeBatch() 方法时,Statement会将命令列表中缓存的所有sql语句一次性提交给数据库。这可以有效的减少网络通信带来的性能消耗。

clearBath()用于清空命令表中缓存的所有sql语句。


preparedStatement 也支持批处理。原理相同

addBatch()不带参数  。想命令列表中添加一条sql语句



封装事务

 Java提供了一个类ThreadLocal

该类的作用是, 在同一个线程中的不同模块间共享数据。

数据共享是根据线程区分的。不同线程间不共享数据。


 举例:刷卡消费

每个人就是一个线程,他们在不同商店消费时,数据会互相影响

但是不同人之间的数据不会产生影响  就是不同线之间的数据不会共享

package day02.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.*;

/**
 * DAO父类
 * 
 * 基础类
 * 提供所有的DAO 都需要兼备的特性
 * 
 * @author ssd
 *
 */
public class BaseDAO {
	/**
	 * java.util.Properties类
	 * 用于读取properties文本文件类
	 * properties文件是一个纯文本的文件,里面的内容的定义有格式的要求
	 *        必须是key=value的形式,且以行为单位一行只记录一条数据
	 *properties类可以方便的读取properties文件,并将内容
	 *以类似HashMap的形式进行读取。注意!读取的都是字符串
	 *
	 *properties通常都是当做配置文件进行使用的。
	 */
	//共享同一个线程中数据的threadLocal
	/**
	 * ThreadLocal 是在同一个线程中不同模块中共享数据使用过的
	 * ThreadLocal内部很简单
	 * 就是维护者一个HashMap
	 * 其中一个Key存放的是每一个线程
	 * value就是存放在不同模块之间要共享的数据
	 * 每个ThreadLocal实例,只能保存一个共享数据
	 * 不同的线程看到的是应该是同一个ThreadLocal实例,但是获取的
	 * 是不同的数据,因为在线程间不共享。每个线程在不同模块中共享数据
	 * 
	 * 如果要想保存两个数据我们可以再建立一个ThreadLocal实例
	 * 
	 */
	private static ThreadLocal<Connection> localConn = new ThreadLocal<Connection>();
	private static Properties properties = new Properties();
	private static String driver = "oracle.jdbc.driver.OracleDriver";
	private static String url = "jdbc:oracle:thin:@localhost:1521:orcl";
	private static String user = "scott";
	private static String pwd = "Shen2014";
	/**
	 * 在静态初始化中注册驱动
	 * 驱动不需要重复注册,所以静态初始化最适合注册驱动
	 * @return
	 */
	static {
		try{
			/**
			 * 加载配置文件,读取配置信息
			 */
			
			properties.load(BaseDAO.class.getClassLoader().getResourceAsStream("" +
			"day02/dao/db.properties" ));
			properties.load(BaseDAO.class.getClassLoader().getResourceAsStream("" +
					"day02/dao/db.properties" ));
			
			System.out.println(properties.getProperty("jdbc.driver"));
			/**
			 * 通过Properties的方法getProperty(String key)
			 * 方法可以将properties文件中
			 * jdbc.driver=oracle.jdbc.driver.OracleDriver
			 * 数据获取。获得的方法就是将jdbc.driver作为参数调用方法
			 * 返回的就是等号右边的oracle.jdbc.driver.OracleDriver
			 */
			driver = properties.getProperty("jdbc.driver");
			url = properties.getProperty("jdbc.url");
			pwd = properties.getProperty("jdbc.pwd");
			user = properties.getProperty("jdbc.user");
			
//			加载驱动
			Class.forName(driver);
			/**
			 * oracle.jdbc.driver.OracleDriver类
			 * 在Class.froName()的时候被载入JVM
			 * OracleDriver 是JDBC中的Driver 的子类
			 * 他被要求在静态初始化的时候要将自身驱动的信息
			 * 通过DriverManager 的静态方法注册进去,这样DriverManager就
			 * 知道应该如何通过OracleDriver去连接数据库了。
			 * 所以之后就可以公国DriverManager 的另一个静态方法:
			 *   getConnection()来根据之前的注册的驱动信息来获取连接了。
			 */
			
		}catch (Exception e){
			e.printStackTrace();
			//若注册失败,我们要通知调用者
			throw new RuntimeException(e);
			
			
		}
	}
	/**
	 *提交事务
	 */
	protected void commit(){
		/**
		 * 先去线程共享中看看当前调用搞该方法的线程是否共享过
		 * Connection,若有,就提交事务
		 */
		Connection conn = localConn.get();
		if(conn != null){
			try{
				conn.commit();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	/**
	 * 事务回滚
	 */
	protected void rollback(){
		Connection conn = localConn.get();
		if(conn !=null){
			try{
				conn.rollback();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	/**
	 * 获取数据库连接对象Connection
	 * @return
	 * @throws SQLException  当连接失败时抛出异常
	 */
	protected static Connection getConnection() throws SQLException{
		/**
		 * 当一个线程调用该方法要获取连接的时候,我们要先检查之前这个线程是否已经获取过一个连接了,若有,就不再
		 * 创建了
		 */
		Connection conn = localConn.get();
		//若为空,说明这个线程第一次获取连接。
		if(conn == null){
			//穿件数据库的连接
			conn = DriverManager.getConnection(url,user,pwd);
			//将创建出来的连接放到线程共享中
			localConn.set(conn);
		}
		return conn;
		
	}
	protected static void closeConnection (Connection conn){
		if(conn != null){
			try{
				conn.close();
				
			}catch(SQLException e){
				e.printStackTrace();
			}
		}
	}
}


package day02.entities;

import java.io.Serializable;

/**
 * UserInfo实体类
 * 对应数据库中的UserInfo表
 * @author ssd
 *
 */

public class UserInfo implements Serializable {
	private static final long serialVersionUID = 1L;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	private String id;
	private String name;
	private String password;
	private int age;
	private String sex;
	private String email;
	

}


package day02.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;


import day02.entities.UserInfo;

/**
 * 针对用户进行操作的DAO
 * @author ssd
 *
 */

public class UserInfoDAO extends BaseDAO {
	/**
	 * SQL 语句常量定义
	 * @param userInfo
	 * @return
	 */
	private static final String INSERT = "INSERT INTO userinfo(" +
			"id,name,password,age,sex,email" +
			") VALUES(" +
			"sys_guid(),?,?,?,?,?" +
			")";
	public boolean save(UserInfo userInfo){
		return false;
		
	}
	
	public boolean save(List<UserInfo> userInfos){
		Connection conn = null;
		try {
			conn = getConnection();
			conn.setAutoCommit(false);
			PreparedStatement state = conn.prepareStatement(INSERT);
			long start = System.currentTimeMillis();
			for(UserInfo userInfo:userInfos){
				state.setString(1, userInfo.getName());
				state.setString(2,userInfo.getPassword());
				state.setInt(3, userInfo.getAge());
				state.setString(4,userInfo.getSex());
				state.setString(5,userInfo.getEmail());
				state.addBatch();
			}
			state.executeBatch();//批处理执行之前缓存的所有的sql
			conn.commit();//手动提交
			long end = System.currentTimeMillis();
			System.out.println("操作完成,耗时:" +(end - start) +
					"毫秒");
			return true ;//正常结束 返回一个true		
		}catch (Exception e){
			e.printStackTrace();
			//这个是在执行中间捕获的异常,就是在执行中间出现错误的时候我们要回滚
			if(conn !=null){
				try{
				conn.rollback();
				}catch(SQLException e1){
					e1.printStackTrace();
				}
				
			}
		}finally{
			if(conn !=null){
				try{
					closeConnection(conn);
				   }catch(Exception e){
					e.printStackTrace();
				}
			}
			
		}
		return false;
		
	}
	
	//创建表
	public void createTable(){
		Connection conn = null;
		try{
			conn = getConnection();
			Statement state = conn.createStatement();
			String sql = "CREATE TABLE userinfo(" +
					"id varchar2(36) PRIMARY KEY," +
					"name varchar2(30)," +
					"password varchar2(50)," +
					"age NUMBER (2)," +
					"sex varchar2(2)," +
					"email varchar2(50)" +
					")";
			if(!state.execute(sql)){
				System.out.println("创建完毕");
			}
			
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(conn !=null){
			closeConnection(conn);
			}
			
		}
	}
	public static void main(String[] args){
		UserInfoDAO dao = new UserInfoDAO();
		dao.createTable();
	}

}





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值