JDBC与数据库事务、连接池

Java 中的数据存储技术

在这里插入图片描述

JDBC

在这里插入图片描述在这里插入图片描述

JDBC体系结构

在这里插入图片描述

JDBC 的API

在这里插入图片描述

Java数据类型与MySQL数据类型对应关系

在这里插入图片描述

通过 JDBC 访问数据库的步骤

在这里插入图片描述

1.获取驱动

在这里插入图片描述
在这里插入图片描述

2.建立连接

在这里插入图片描述

连接数据库的URL

在这里插入图片描述

3.操作数据表

在这里插入图片描述

Statement 与 PreparedStatement

SQL注入攻击

  • SQL注入攻击的主要原因在于SQL语句在编译的编译方式,通过Statement方式访问数据库,SQL语句是先通过字符串拼接,然后才是DBServer的编译器对SQL语句进行编译
SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1
  • 为了防止防范 SQL 注入,只要用 PreparedStatement (从 Statement 扩展而来) 取代 Statement 就可以了

在这里插入图片描述
在这里插入图片描述

4. 获取SQL执行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5. 释放资源

在这里插入图片描述

public class JDBCUtils {
	/**
	 * 
	 * @Description 获取数据库的连接
	 */
	public static Connection getConnection() throws Exception {
		InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
		Properties pros = new Properties();
		pros.load(is); // 1.读取配置文件中的4个基本信息

		String driverClass = pros.getProperty("driverClass"); // 2.获取 Driver 实现类对象:使用反射
		Class.forName(driverClass);

		String url = pros.getProperty("url"); // 3.提供要连接的数据库

		String user = pros.getProperty("user");// 4.提供连接需要的用户名和密码
		String password = pros.getProperty("password");

		Connection conn = DriverManager.getConnection(url, user, password);// 5.获取连接
		return conn;
	}

	/**
	 * 
	 * @Description 关闭资源操作
	 */
	public static void closeResource(Connection conn,Statement ps,ResultSet rs){
		try {
			if(ps != null)
				ps.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try {
			if(conn != null)
				conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try {
			if(rs != null)
				rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
public <T> T getInstance(Class<T> clazz,String sql, Object... args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = JDBCUtils.getConnection();

			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) { // 为编译后的 Sql 传参
				ps.setObject(i + 1, args[i]);
			}

			rs = ps.executeQuery();
			// 获取结果集的元数据 :ResultSetMetaData
			ResultSetMetaData rsmd = rs.getMetaData();
			// 通过ResultSetMetaData获取结果集中的列数
			int columnCount = rsmd.getColumnCount();

			/**
			 * 如果返回多条记录
			 * while(rs.next()){
			 * 		//获取当前这条数据的各个字段值
			 * 		int id = resultSet.getInt(1);
			 * 		String name = resultSet.getString(2);
			 * 		String email = resultSet.getString(3);
			 * 		Date birth = resultSet.getDate(4);
			 * 		//方式一:
			 * 		System.out.println("id = " + id + ",name = " + name + ",email = " + email + ",birth = " + birth);
			 *		//方式二:
			 * 		Object[] data = new Object[]{id,name,email,birth};
			 * 		//方式三:将数据封装为一个对象(推荐)
			 * 		Customer cst = new Customer(id, name, email, birth);
			 * 		System.out.println(cst);
			 * }
			 */
			if (rs.next()) { // next():判断结果集的下一条是否有数据,如果有数据返回true,并指针下移;如果返回false,指针不会下移
				T t = clazz.newInstance();
				// 处理结果集一行数据中的每一个列
				for (int i = 0; i < columnCount; i++) {
					// 获取列值
					Object columValue = rs.getObject(i + 1);

					// 获取每个列的列名
					// String columnName = rsmd.getColumnName(i + 1);
					String columnLabel = rsmd.getColumnLabel(i + 1);

					// 给t对象指定的columnName属性,赋值为columValue:通过反射
					Field field = clazz.getDeclaredField(columnLabel);
					field.setAccessible(true);
					field.set(t, columValue);
				}
				return t;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, ps, rs);
		}

		return null;
	}

向数据表中插入、读取大数据:BLOB字段

在这里插入图片描述
在这里插入图片描述

// 插入大字段数据
Connection conn = JDBCUtils.getConnection();
String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1,"袁浩");
ps.setObject(2, "yuan@qq.com");
ps.setObject(3,"1992-09-08");
FileInputStream is = new FileInputStream(new File("girl.jpg"));
ps.setBlob(4, is);
ps.execute();
JDBCUtils.closeResource(conn, ps,null);

// 查询大字段数据
Connection conn = null;
PreparedStatement ps = null;
InputStream is = null;
FileOutputStream fos = null;
ResultSet rs = null;
try {
	conn = JDBCUtils.getConnection();
	String sql = "select id,name,email,birth,photo from customers where id = ?";
	ps = conn.prepareStatement(sql);
	ps.setInt(1, 21);
	rs = ps.executeQuery();
	if(rs.next()){
		/**
		 * 方式一
		 * int id = rs.getInt(1);
		 * String name = rs.getString(2);
		 * String email = rs.getString(3);
		 * Date birth = rs.getDate(4);
		 */
		//方式二
		int id = rs.getInt("id");
		String name = rs.getString("name");
		String email = rs.getString("email");
		Date birth = rs.getDate("birth");
		
		Customer cust = new Customer(id, name, email, birth);
		System.out.println(cust);
		
		//将Blob类型的字段下载下来,以文件的方式保存在本地
		Blob photo = rs.getBlob("photo");
		is = photo.getBinaryStream();
		fos = new FileOutputStream("zhangyuhao.jpg");
		byte[] buffer = new byte[1024];
		int len;
		while((len = is.read(buffer)) != -1){
			fos.write(buffer, 0, len);
		}
		
	}
} catch (Exception e) {
	e.printStackTrace();
}finally{
	
	try {
		if(is != null)
			is.close();
	} catch (IOException e) {
		e.printStackTrace();
	}
	
	try {
		if(fos != null)
			fos.close();
	} catch (IOException e) {
		e.printStackTrace();
	}
	
	JDBCUtils.closeResource(conn, ps, rs);
}

批量插入数据

在这里插入图片描述

Connection conn = null;
PreparedStatement ps = null;
try {
	long start = System.currentTimeMillis();
	conn = JDBCUtils.getConnection();
	conn.setAutoCommit(false);//设置不允许自动提交数据
	String sql = "insert into goods(name)values(?)";
	ps = conn.prepareStatement(sql);
	for(int i = 1;i <= 1000000;i++){
		ps.setObject(1, "name_" + i);
		ps.addBatch();//1."攒"sql
		if(i % 500 == 0){
			ps.executeBatch();//2.执行batch
			ps.clearBatch();//3.清空batch
		}
	}
	//提交数据
	conn.commit();
	long end = System.currentTimeMillis();
	System.out.println("花费的时间为:" + (end - start));//20000:83065 -- 565
} catch (Exception e) {								//1000000:16086 -- 5114
	e.printStackTrace();
}finally{
	JDBCUtils.closeResource(conn, ps,null);
	
}

数据库的事务

在这里插入图片描述
在这里插入图片描述

数据库事务的执行过程

COMMIT 和 ROLLBACK 的优点、数据完整性

在这里插入图片描述

COMMIT 、ROLLBACK 前

在这里插入图片描述

COMMIT 后

在这里插入图片描述

ROLLBACK 后

在这里插入图片描述

ACID

在这里插入图片描述

JDBC 事务处理

在这里插入图片描述

Connection conn = null;
try {
	conn = JDBCUtils.getConnection();
	System.out.println(conn.getAutoCommit());//true
	//1.取消数据的自动提交
	conn.setAutoCommit(false);
	
	String sql1 = "update user_table set balance = balance - 100 where user = ?";
	update(conn,sql1, "AA");
	
	//模拟网络异常
	System.out.println(10 / 0);
	
	String sql2 = "update user_table set balance = balance + 100 where user = ?";
	update(conn,sql2, "BB");
	
	System.out.println("转账成功");
	
	//2.提交数据
	conn.commit();
	
} catch (Exception e) {
	e.printStackTrace();
	//3.回滚数据
	try {
		conn.rollback();
	} catch (SQLException e1) {
		e1.printStackTrace();
	}
}finally{
	// 关闭连接时,也会自动的提交数据
	JDBCUtils.closeResource(conn, null,null);
}

事务的隔离级别

  • 数据库的隔离级别即为事务的隔离级别

在这里插入图片描述
在这里插入图片描述

数据库连接池

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 常见的数据库连接池:C3P0→DBCP–Apache CommonPool→Druid→Hikari(流行时间排序)
  • Druid的功能特点:可以对SQL性能进行监控,但是MySQL自身有慢日志可以查看
  • Hikari是现在默认的数据库连接池

DateSource 类

在这里插入图片描述

  • 通过数据库连接池得到的连接对象,使用conn.close(),并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值