转载

Java 之 JDBC(二)

前面我们已经知道了一些常用的JDBC操作,接下来我们继续深入,继续改进我们的DAO。

Java 之 JDBC (一)

一、JDBC池链接

1、没有池的情况下:

Java 之 JDBC(二)

总之就是不使用池的情况下:每次操作都需要进行连接数据库,连接中需要将Connection加载进内存中,验证用户名和密码等都需要话费时间。

2、认识池

Java 之 JDBC(二)
1、 池就是一种容纳对象的容器
2、 连接池就是保存数据库连接对象的容器
3、 在连接池中我们会预先创建一定数量的连接对象,当需要数据库连接的时候,只要从数据库连接池中取出一个,使用完毕之后就再放回去,这些连接对象是以一种循环队列来存放的,取的时候从头开始,放回的时候放在尾部。
4、 通过设置最大连接数量来防止系统无止尽的与数据库连接
5、 连接池中可以设置监听机制,用来测试连接的数量
复制代码
Java 之 JDBC(二)

连接池中的属性:

Java 之 JDBC(二)

3、连接池的使用

Java 之 JDBC(二)
1、 连接池是使用 java.sql.DataSource接口来表示连接池的
2、 DataSource和jdbc一样,也是只提供一个接口,由第三方组织来提供,所以连接池不同的厂家,有不同的连接池
复制代码
Java 之 JDBC(二)

4、详细步骤

DBCP的使用

Java 之 JDBC(二)

以下代码就是获取数据库连接池,并获取连接对象。

Java 之 JDBC(二)

二、配置信息

第一步 文件创建

1、项目目录下新建一个resource文件夹 
2、编写db.properties文件
复制代码
Java 之 JDBC(二)

文件内容为:

// 记录配置信息
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mytest?rewriteBatchedStatements=true
username=root
password=zjj19970517
maxActive=8
复制代码

为什么要使用配置文件?

Java 之 JDBC(二)

第二步 文件读取

例子:

Java 之 JDBC(二)

我们可以改写我们的utils类:(通过静态代码块执行获取连接池)

Java 之 JDBC(二)

三、Druid使用

Java 之 JDBC(二)

Druid地址

Druid是一个JDBC组件库,包括数据库连接池、SQL Parser等组件。DruidDataSource是最好的数据库连接池。

DBCP迁移到Druid

DruidDataSource的配置是兼容DBCP的。从DBCP迁移到DruidDataSource,只需要修改数据源的实现类就可以了。
复制代码
Java 之 JDBC(二)

四、DAO重构改进

Java 之 JDBC(二)

1、抽取DML方法

数据查询语言DQL
数据操纵语言DML
数据定义语言DDL
数据控制语言DCL。
复制代码
/**
	 * 更新操作公共方法
	 * @param sql      预编译sql语句
	 * @param params   参数数组
	 * @return
	 */
	public int _executeUpdate(String sql, Object...params) {
		
		Connection conn = null;
		PreparedStatement ps = null;
		
		try {
			// 连接数据库
			conn = JDBCUtils.getConnection();	
			// 创建预编译
			ps = conn.prepareStatement(sql);
			// 设置参数
			for(int i= 0 ; i < params.length; i++) {
				ps.setObject(i+1, params[i]);
			}
			
			// 执行更新
			return ps.executeUpdate(); // 返回更新的行数
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.close(conn, ps, null);
		}
		return -1; // 如果更新失败,返回-1
	}
复制代码

使用如下:

/**
	 * 存储学生
	 * @param stu
	 */
	public void save(Student stu) {
		String sql = "insert into student (name, age) values (? , ?)";
		this._executeUpdate(sql, stu.getName(), stu.getAge()); //直接调用
	}
复制代码
Java 之 JDBC(二)

为了今后使用方便我们把 _executeUpdate 方法抽取出来,放入一个 CRUDTemplate 的模版类中。

package com.meils.jdbc.utils;

import java.sql.Connection;
import java.sql.PreparedStatement;

/**
 * CRUD操作模版
 * @author apple
 *
 */
public class CRUDTemplate {
	/**
	 * 更新操作公共方法
	 * @param sql      预编译sql语句
	 * @param params   参数数组
	 * @return
	 */
	public static int _executeUpdate(String sql, Object...params) {
		
		Connection conn = null;
		PreparedStatement ps = null;
		
		try {
			// 连接数据库
			conn = JDBCUtils.getConnection();	
			// 创建预编译
			ps = conn.prepareStatement(sql);
			// 设置参数
			for(int i= 0 ; i < params.length; i++) {
				ps.setObject(i+1, params[i]);
			}
			
			// 执行更新
			return ps.executeUpdate(); // 返回更新的行数
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.close(conn, ps, null);
		}
		return -1; // 如果更新失败,返回-1
	}
}

复制代码

2、抽取DQL方法

第一步 新建handle处理层接口

新建一个包: com.meils.jdbc.handle

// IResultSetHandle.java

package com.meils.jdbc.handle;

import java.sql.ResultSet;
import java.util.List;

/**
 * 结果集处理接口
 * @author apple
 *
 */

// 这里传入了类型,T为我们通过这个方法处理后要返回的类型
public interface IResultSetHandle<T>{
	/**
	 * 处理结果集
	 * @param rs  传入结果集
	 * @return    返回List集合
	 */
	T handle(ResultSet rs);
}
复制代码

第二步 实现接口类

在student的dao实现接口类中定义内部类

/**
 * 结果集处理 实现类
 * @author apple
 *
 */
 
 // 因为具体到某一个dao层的时候我们就知道了我们想要的类型了,所以传入<List<Student>>
class StuResultSetHandle implements IResultSetHandle <List<Student>>{

	@Override
	public List<Student> handle(ResultSet rs) {
		List<Student> list = new ArrayList<Student>();
		try {
			while (rs.next()) {
				Student stu = new Student();
				stu.setName(rs.getString("name"));
				stu.setAge(rs.getInt("age"));
				stu.setId(rs.getInt("id"));
				list.add(stu);
			}
			return list; // 返回集合
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
}
复制代码

第三步 编写DQL模版方法

// CRUDTemplate.java

package com.meils.jdbc.utils;

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

import com.meils.jdbc.handle.IResultSetHandle;

/**
 * CRUD操作模版
 * @author apple
 *
 */
public class CRUDTemplate {
	/**
	 * 更新操作公共方法
	 * @param sql      预编译sql语句
	 * @param params   参数数组
	 * @return
	 */
	public static int _executeUpdate(String sql, Object...params) {
		
		Connection conn = null;
		PreparedStatement ps = null;
		
		try {
			// 连接数据库
			conn = JDBCUtils.getConnection();	
			// 创建预编译
			ps = conn.prepareStatement(sql);
			// 设置参数
			for(int i= 0 ; i < params.length; i++) {
				ps.setObject(i+1, params[i]);
			}
			
			// 执行更新
			return ps.executeUpdate(); // 返回更新的行数
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.close(conn, ps, null);
		}
		return -1; // 如果更新失败,返回-1
	}
	
	/**
	 * 查询 公共方法
	 * @param sql  sql预编译语句
	 * @param rh   结果集处理的实现对象
	 * @param params  要给sql语句传入的参数
	 * @return		返回一个结果集
	 */
	// 这里我们也使用范型,因为我们这里要返回结果集处理方法处理完毕之后的集合,但是处理完毕的结果集我们并不知道是什么类型,因此我们需要通过范型来设置变化的类型
	public static <T>T _executeQuery(String sql, IResultSetHandle<T> rh, Object... params) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		
		try {

			conn = JDBCUtils.getConnection();
			ps = conn.prepareStatement(sql);
			for (int i = 0; i < params.length; i++) {
				ps.setObject(i + 1, params[i]);
			}
			rs = ps.executeQuery();
			return rh.handle(rs); // 处理结果集

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.close(conn, ps, rs);
		}
		return null;
	}
}

复制代码

第四步 使用以下

@Override
	public Student findOne(int id) {
		
		String sql = "select * from student where id = ?";
		IResultSetHandle <List<Student>> result = new StuResultSetHandle();
		List<Student> list = CRUDTemplate._executeQuery(sql,result,id);
		return list.size() == 1 ? list.get(0) : null;
}
复制代码
原文  https://juejin.im/post/5c79cf6e5188255dbd5855f5
正文到此结束
Loading...