Java 15---JDBC批处理,事务,并发,DAO模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37527943/article/details/85448486

导读

1.JDBC批处理
2.JDBC事务处理
3.事务并发问题
4.JDBCTemplate
5.DAO模式

JDBC批处理

添加10000个用户到用户表

批处理:一次发送多个数据给服务器,服务器一个一个执行,提高效率
	addBatch():把语句,参数添加到PreparedStatement中
	executeBatch():一次把所有数据发送给服务器,有服务器一条一条执行

在这里插入图片描述

JDBC事务处理

事务回顾

可以保证多个操作要么都成功要么都失败
在Java中默认所有的操作都是自动提交
Java中什么时候考虑使用事务呢?一个业务如果涉及多个DML操作,可以使用事务控制

下单:
	生成订单
	生成明细
	
	1.生成订单和生成订单明细在同一个事务中,需要使用同一个连接,Connection
	2.但凡有一个出问题,就回滚,如果两个都成功,则提交
	3.提交模式改成手动提交

Java事务控制步骤:	
try{
	建立连接;
	设置为手动提交模式;
	操作1;
	操作2;
	都成功则提交;
}catch(){
	但凡有问题则回滚;
}finally{
	释放连接;
}
	
事务相关的方法:Connection中
	conn.setAutoCommit(false);  --手动提交
	conn.commit();              --提交
	conn.rollback();            --回滚
	
	注意点:这些仅针对于当前这个Connection对象
	
	OrderJDBC orderJDBC = new OrderJDBC();
		OrderDetailJDBC detailJDBC = new OrderDetailJDBC();
		Connection conn = null;
		try {
			//完成下单业务
			//1.生成订单编号
			long orderId = orderJDBC.generateOrderId();
			//先获取连接
			conn = ConnectionFactory.getConnection();
			//设置为手动提交模式
			conn.setAutoCommit(false);
			//2.生成订单
			//把订单编号赋给order
			order.setId(orderId);
			orderJDBC.addOrder(order,conn);
			//3.生成订单明细
			for(int i=0; i<list.size();i++) {
				list.get(i).setOrderId(orderId);//生成的订单号赋给明细
				detailJDBC.addOrderDetail(list.get(i),conn);
			}
			//都成功提交
			conn.commit();
			return true;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			//如果有问题,则回滚
			try {
				conn.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			return false;
		}finally {
			DBUtils.close(conn);
		}

事务并发问题

事务并发引起的问题(等级越来越高,并发性越差):
1.脏读:一个事务读到了另一个事务未提交的更新数据,
	应该要避免 
2.不可重复读:一个事务期间两次读取同一个数据结果不同,
	通常不需要避免的
3.虚读/幻影读:一个事务期间两次读取的同一个统计结果不同(比如求和,求平均)
	通常不需要避免的
事务隔离级别:	
0 TRANSACTION_NONE:不支持事务
1 TRANSACTION_READ_UNCOMMITTED:脏读
2 TRANSACTION_READ_COMMITTED:避免脏读
4 TRANSACTION_REPEATABLE_READ:避免不可重复读
8 TRANSACTION_SERIALIAZABLE:避免虚读

事务隔离级别越高,并发性越差
Oracle只支持2,8, 默认是2
conn.setTransactionIsolation(level);//可以写名字,也可以写数字

JDBCTemplate

封装通用的增删改查步骤
分为两种,一种是针对于增删改,另一种是针对查封装

对于增删改

package com.hwua.util;

import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
 * 设置占位符值的接口
 * @author Mary
 *
 */
public interface PreparedStatementSetter {
	//设置占位符的值
	public void setValues(PreparedStatement pstmt) 
			throws SQLException;
}

针对查

package com.hwua.util;

import java.sql.ResultSet;
import java.sql.SQLException;
/**
 * 处理结果集的接口
 * @author Mary
 *
 */
public interface ResultSetHandler {
	/**
	 * 处理结果集
	 * @param rs 结果集
	 * @throws SQLException
	 */
	public void handleRS(ResultSet rs) 
			throws SQLException;
}
package com.hwua.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 模版类
 * 封装通用的增删改,查方法
 * @author Mary
 *
 */
public class JDBCTemplate {
	//增删改
	//这里要求实现PreparedStatementSetter接口的对象,是面向接口编程
	public int update(String sql,PreparedStatementSetter setter)
			throws SQLException {
		//1,2
		Connection conn = ConnectionFactory.getConnection();
		//3
		PreparedStatement pstmt = conn.prepareStatement(sql);
		//4
		//先设置占位符的值
		if(setter!=null) {
			setter.setValues(pstmt);
		}
		//执行
		int rows = pstmt.executeUpdate();
		//6
		DBUtils.close(pstmt, conn);
		return rows;
	}

	//查询
	public void query(String sql,
			PreparedStatementSetter setter,
			ResultSetHandler handler) throws SQLException {
		//1,2
		Connection conn = ConnectionFactory.getConnection();
		//3
		PreparedStatement pstmt = conn.prepareStatement(sql);
		//4
		if(setter!=null) {
			setter.setValues(pstmt);
		}
		ResultSet rs = pstmt.executeQuery();
		//5.处理结果集
		if(handler!=null) {
			handler.handleRS(rs);
		}
		//6.
		DBUtils.close(rs, pstmt, conn);
	}
}

测试类中的实现

public int addUser(User user) throws SQLException {
		String sql = "INSERT INTO t_user (id,username,password,sex,"
				+ "id_number,tel,addr) "
				+ "VALUES(t_user_id_seq.NEXTVAL,?,?,?,?,?,?)";
		//调用通用的增删改方法
		return update(sql, new PreparedStatementSetter() {	
			@Override
			public void setValues(PreparedStatement pstmt) throws SQLException {
				pstmt.setString(1, user.getUsername());
				pstmt.setString(2, user.getPassword());
				pstmt.setInt(3, user.getSex());
				pstmt.setString(4, user.getIdNumber());
				pstmt.setString(5, user.getTel());
				pstmt.setString(6, user.getAddr());
			}
		});

	}

/**
	 * 通过用户名查找用户
	 * @param username:用户名
	 * @return 查找到的用户信息  null:没有对应的用户
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public List<User> queryUser(String username) throws SQLException {
		List<User> list = new ArrayList<>();	
		String sql = "SELECT id,username,password,sex,id_number,"
				+ "tel,addr FROM t_user WHERE username=?";
		query(sql, new PreparedStatementSetter() {			
			@Override
			public void setValues(PreparedStatement pstmt) throws SQLException {
				//放置设置占位符的值的代码
				pstmt.setString(1, username);
			}
		}, new ResultSetHandler() {			
			@Override
			public void handleRS(ResultSet rs) throws SQLException {
				//放置结果集处理的代码
				if(rs.next()) {
					User user = new User(rs.getLong(1), rs.getString(2), rs.getString(3), rs.getInt(4), rs.getString(5),
							rs.getString(6), rs.getString(7));
					list.add(user);
				}
			}
		});
		return list;
	}

DAO模式

DAO:Data Access Object,数据访问对象
把数据访问细节封装起来
一个原子性的增删改查封装成一个方法

	一个表对应一个DAO
		一个接口+一个实现类
		命名:
		IUserDao   UserDaoImpl
		IOrderDao  OrderDaoImpl
		包:
		com.hwua.dao   com.hwua.dao.impl

Java<==>JDBC<==>数据库SQL

登录:
	输入用户和密码,判断是否正确
	利用查询查找对应的用户是否存在
	
注册:
	输入各种信息
	查询是否合法
	合法添加到数据库

分层思想:
	界面层<==>业务逻辑层<==>DAO层
	
	界面层:与用户打交互,具体做这个业务调用业务逻辑层
	业务逻辑层:完成这个业务
	           可能涉及到与数据库的交互调用DAO
	DAO层:数据访问层

猜你喜欢

转载自blog.csdn.net/qq_37527943/article/details/85448486