JDBC高级,数据库连接池和DbUtils
1. BaseDao封装
1.1 BaseDao 通用查询方法封装
1.1.1 ORM思想
ORM思想
数据库数据行 ==> Java中的类对象
数据行:
字段名字,对应当前字段的数据
类对象:
成员变量名字
要求:
1. 字段名 <==> 成员变量名
2. 字段数据类型 <==> 成员变量数据类型一致。
1.1.2 通用查询方法功能分析
期望:
1. 可以处理select 对应的 DQL 语句
2. 根据用户约定,可以得到任意数据类型
3. 查询返回的数据,可以是多个,可以是一个
SQL语句:
1. SQL有可能带有参数
2. 对应当前SQL语句的参数列表
用户指定类型问题:
1. 任意类型:
使用泛型来约束数据类型,用户既可以使用任意类型,同时也可以满足数据类型一
致化要求。
2. 类对象问题:
Person类型 ==> Person类对象
Student类型 ==> Student类对象
方法内需要有创建对应类对象的能力:
a. new + 构造方法
b. 反射通过Class类对象,获取Constructor对象,调用newInstance方
法 【选择】
3. 方法参数怎么写???
a. Class类对象
b. 泛型约束
Class<T>
传入参数:
Person.class ==> Class<Person> T ==> Person
Worker.class ==> Class<Worker> T ==> Worker
方法参数:
1. String sql
2. Class<T> cls
3. Object... parameters [不定长参数有且只能是方法参数列表的最后一个]
方法返回值:
List<T>
LinkedList ArrayList
方法声明:
public <T> List<T> query(String sql, Class<T> cls, Object... parameters);
1.1.3 方法流程分析
1. 准备必要的变量
2. 获取数据库连接
3. 预处理SQL语句
4. 赋值SQL语句参数
5. 执行方法,获取结果集对象
【重点】
6. 解析结果集
6.1 想要获取字段名 ==> 成员变量名字 [字段名获取]
【结果集元数据】 MetaData
getColumnName
getColumnCount
6.2 取出数据 ==> 赋值成员变量 [数据类型一致]
【BeanUtils】
符合JavaBean规范的对象赋值,取值,拷贝操作工具类
7. 关闭资源
8. 返回List集合
【补充知识点 结果集元数据】
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
System.out.println("columnCount : " + columnCount);
System.out.println("ColumnName : " + metaData.getColumnName(1));
System.out.println("ColumnName : " + metaData.getColumnName(2));
System.out.println("ColumnName : " + metaData.getColumnName(3));
System.out.println("ColumnName : " + metaData.getColumnName(4));
System.out.println("ColumnName : " + metaData.getColumnName(5));
【补充知识点 BeanUtils】
符合JavaBean规范类对象,赋值,取值,拷贝的工具类
依赖第三方Jar
commons-beanutils-1.8.3.jar
commons-logging-1.1.3.jar
beanutils 依赖于 logging 没有依赖,无法使用
涉及到的方法:
static void setProperty(Object bean, String name, Object value);
设置指定符合JavaBean规范的类对象中,对应成员变量赋值操作。
bean:
任何一个符合JavaBean规范的类对象
name:
当前符合JavaBean规范类对象对应的成员变量名字
value:
需要赋值给对应成员变量的数据
static String getProperty(Object bean, String name);
获取符合JavaBean规范类对象中的指定成员变量数据,返回值是String类型
bean:
任何一个符合JavaBean规范的类对象
name:
指定成员变量的名字
返回值:
String 对应当前成员变量数据的String类型。
static void copyProperties(Object dest, Object src);
从src中拷贝数据到dest中,要求两个对象都是符合JavaBean规范,并且是同一个类型
对象。
1.1.4 BaseDao query方法实现
public <T> List<T> query(String sql, Class<T> cls, Object... parameters)
throws SQLException, NoSuchMethodException, IllegalAccessException,
InvocationTargetException, InstantiationException {
ResultSet resultSet = null;
Connection connection = null;
PreparedStatement statement = null;
connection = JDBCUtil.getConnection();
statement = connection.prepareStatement(sql);
int parameterCount = statement.getParameterMetaData().getParameterCount();
if (parameters != null && parameterCount == parameters.length && parameterCount != 0) {
for (int i = 0; i < parameters.length; i++) {
statement.setObject(i + 1, parameters[i]);
}
}
resultSet = statement.executeQuery();
ResultSetMetaData metaData = resultSet.getMetaData();
List<T> list = new ArrayList<>();
while (resultSet.next()) {
T t = cls.getConstructor().newInstance();
for (int i = 1; i <= metaData.getColumnCount(); i++) {
String fieldName = metaData.getColumnName(i);
Object object = resultSet.getObject(fieldName);
BeanUtils.setProperty(t, fieldName, object);
}
list.add(t);
}
JDBCUtil.close(resultSet, statement, connection);
return list.isEmpty() ? null : list;
}
2. 数据库连接池
2.1 回顾线程池
线程池的优点:
1. 降低了线程创建和销毁的时间浪费
2. 可以自行增加线程对象,同时也可以根据当前线程池,线程的空闲时间,进行多余线
程关闭
3. 提交任务方便,不再需要考虑针对线程的继承或者遵从问题。Runnable target
数据库操作存在类似问题
针对于数据库的连接对象Connection 需要频繁的打开和关闭,浪费时间。同时可以会出现多线程打开数据库操作的情况。
使用数据库连接池来解决类似的问题!!!
2.2 数据库连接池的核心参数
1. 数据库连接对象获取方式必要的参数:
driverClass jdbcUrl userName password
2. 初始化数据库连接池容量
3. 最大数据库连接对象容量
4. 等待时间 Timeout
5. 最小容量
数据库连接池的配置都是通过【配置文件完成】。
数据库连接池对象使用【润物细无声】
C3P0 SSH框架中 Hibernate内置数据库连接池方式
Druid From China Alibaba
2.3 C3P0数据库连接池使用
2.3.1 导包
需要导入第三方Jar包
c3p0-0.9.5.2.jar
mchange-commons-java-0.2.15.jar
2.3.2 c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/javaee2009?useSSL=false</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">30</property>
<property name="minPoolSize">5</property>
<property name="maxStatements">50</property>
<property name="checkoutTimeout">1000</property>
</default-config>
</c3p0-config>
2.3.3 修改JDBCUtil工具类,使用C3P0
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
public static Connection getConnection() {
Connection connection = null;
try {
connection = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
2.4 Druid 数据库连接池
2.4.1 导包
druid-1.2.3.jar
Druid第三方Jar包
2.4.2 Druid数据库连接池配置文件
# druid.properties文件
# 文件名 druid.properties 存储在src目录下
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/javaee2009?useSSL=false
username=root
password=123456
# 初始化数据库连接池容量
initialSize=10
# 最大容量
maxActive=30
# TimeOut 等待超时时间
maxWait=2000
2.4.3 使用Druid优化JDBCUitl工具
package util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCUtil {
private static DataSource dataSource = null;
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("./src/druid.properties"));
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection connection = null;
try {
connection = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void close(AutoCloseable... res) {
try {
for (AutoCloseable re : res) {
if (re != null) {
re.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. DBUtils轻量级ORM框架
3.1 DbUtils工具类
最后更新是2017年7月
核心类 QueryRunner
提供了大量的 Handler 方式,处理方式。
原生 ResultSetHandler
升级版:
BeanHandler<T>(Class<T> cls);
BeanListHandler<T>(Class<T> cls);
ArrayHandler();
ArrayListHandler();
MapHandler();
MapListHandler();
3.2 Handler使用
3.2.1 BeanHandler
@Test
public void testBeanHandler() throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select * from javaee2009.student where id = 10";
Student student = queryRunner.query(sql, new BeanHandler<>(Student.class));
System.out.println(student);
}
3.2.2 BeanListHandler
@Test
public void testBeanListHandler() throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select * from javaee2009.student;";
List<Student> list = queryRunner.query(sql, new BeanListHandler<>(Student.class));
for (Student student : list) {
System.out.println(student);
}
}
3.2.3 ArrayHandler
@Test
public void testArrayHandler() throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select name, age, id, score, info from javaee2009.student where id = ?;";
Object[] objects = queryRunner.query(sql, new ArrayHandler(), 10);
System.out.println(Arrays.toString(objects));
}
3.2.4 ArrayListHandler
@Test
public void testArrayListHandler() throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select name, age, info from javaee2009.student;";
List<Object[]> list = queryRunner.query(sql, new ArrayListHandler());
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
}
3.2.5 MapHandler
@Test
public void testMapHandler() throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select name, age, id, score, info from javaee2009.student where id = ?;";
Map<String, Object> map = queryRunner.query(sql, new MapHandler(), 10);
System.out.println(map);
}
3.2.6 MapListHandler
@Test
public void testMapListHandler() throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
String sql = "select name, age, info from javaee2009.student;";
List<Map<String, Object>> mapList = queryRunner.query(sql, new MapListHandler());
for (Map<String, Object> map : mapList) {
System.out.println(map);
}
}