轻量级 ORM 框架 DbUtils【重点】-12月1日讲课内容
数据库连接池
JDBC
轻量级 ORM 框架 DbUtils【重点】
概述
Commons DbUtils 是 Apache 组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。
jar包
commons-dbutils-1.7.jar
下载路径
http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi
核心 API
// DbUtils 核心类,提供简易的对数据库进行操作的方法
class QueryRunner {}
// update 核心方法对应增删改操作 insert,update,delete
// conn -> 数据库连接
// sql -> sql语句
// params -> 参数列表,这里使用可变长参数,底层是Object类型的数组
int update(Connection conn, String sql, Object... params);
// query 核心方法,对应查询操作
// T 泛型
// conn -> 数据库连接
// sql -> sql语句
// rsh -> 结果集处理器接口,需要传入一个实现类,或者使用匿名内部类的形式并重写handler方法,推荐使用其实现类 BeanHandler 以及 BeanListHandler
// params -> 参数列表,这里使用可变长参数,底层是Object类型的数组
<T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params)
// 结果集映射器接口,核心方法为 handler()
interface ResultSetHandler<T> {}
// 处理符合JavaBean规范的类对象,传入参数是对应JavaBean规范 Class对象,返回一个对应的实体类对象
class BeanHandler<T> implements ResultSetHandler<T> {}
// 处理符合JavaBean规范的实体类,并且返回值是一个List集合包含制定的JavaBean实体类
class BeanListHandler<T> implements ResultSetHandler<List<T>> {}
使用 DbUtils 插入数据
public class Demo1 {
@Test
public void testInsert() {
// 获取 QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 获取连接
Connection connection = JdbcUtils.getConnection();
// 准备SQL语句
String sql = "insert into student(name, age, gender, info) values(?, ?, ?, ?)";
// 准备参数
Object[] parameters = {"刘能", 37, "男", "人生没有如果,只有后果和结果"};
try {
// 执行SQL语句并获取受影响的行数
int affectedRows = queryRunner.update(connection, sql, parameters);
System.out.println("受影响的行数:" + affectedRows);
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtils.close(connection);
}
}
}
使用 DbUtils 修改数据
public class Demo1 {
@Test
public void testUpdate() {
// 获取 QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 获取连接
Connection connection = JdbcUtils.getConnection();
// 准备SQL语句
String sql = "update student set age = ? where id = ?";
// 准备参数
Object[] parameters = {48, 7};
try {
// 执行SQL语句并获取受影响的行数
int affectedRows = queryRunner.update(connection, sql, parameters);
System.out.println("受影响的行数:" + affectedRows);
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtils.close(connection);
}
}
}
使用 DbUtils 删除数据
public class Demo1 {
@Test
public void testDelete() {
// 获取 QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 获取连接
Connection connection = JdbcUtils.getConnection();
// 准备SQL语句
String sql = "delete from student where id = ?";
// 准备参数
Object[] parameters = {7};
try {
// 执行SQL语句并获取受影响的行数
int affectedRows = queryRunner.update(connection, sql, parameters);
System.out.println("受影响的行数:" + affectedRows);
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtils.close(connection);
}
}
}
使用 DbUtils 的 ResultSetHandler 进行查询单条数据【鸡肋】
public class Demo2 {
@Test
public void testQueryOne() {
// 获取QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 获取连接
Connection connection = JdbcUtils.getConnection();
// 准备SQL语句
String sql = "select * from student where id = ?";
// 准备参数
Object[] params = {1};
try {
// 通过匿名内部类实现ResultSetHandler,并重写handler方法,执行SQL语句
Student student = queryRunner.query(connection, sql, new ResultSetHandler<Student>() {
// 重写handler方法
@Override
public Student handle(ResultSet resultSet) throws SQLException {
Student student1 = null;
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String gender = resultSet.getString("gender");
String info = resultSet.getString("info");
student1 = new Student(id, name, age, gender, info);
}
return student1;
}
}, params);
System.out.println(student);
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtils.close(connection);
}
}
}
使用DbUtils 的 BeanHandler 进行查询单条数据
public class Demo3 {
@Test
public void testQuery() {
// 获取QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 准备SQL语句
String sql = "select * from student where id = ?";
// 准备参数
Object[] params = {1};
// 获取连接
Connection connection = JdbcUtils.getConnection();
try {
// 执行SQL语句,传入BeanHandler对象
Student student = queryRunner.query(connection, sql, new BeanHandler<Student>(Student.class), params);
System.out.println(student);
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtils.close(connection);
}
}
}
使用 DbUtils 的 BeanListHandler 进行查询多条数据
public class Demo4 {
@Test
public void testQueryAll() {
// 获取QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 准备SQL语句
String sql = "select * from student";
// 获取连接
Connection connection = JdbcUtils.getConnection();
try {
// 执行SQL语句,传入BeanListHandler对象,获取一个包含实体类对象的集合
List<Student> list = queryRunner.query(connection, sql, new BeanListHandler<Student>(Student.class));
System.out.println(list);
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtils.close(connection);
}
}
}
【补充】使用 DbUtils 的 ArrayHandler 获取包含对应一条数据的数组
// 处理符合JavaBean规范的类对象,能够将数据转为一个Object类型的数组
class ArrayHandler implements ResultSetHandler<Object[]> {}
案例代码
public class Demo5 {
@Test
public void testQueryOne() {
// 获取QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 准备SQL语句
String sql = "select * from student where id = 1";
// 获取连接
Connection connection = JdbcUtils.getConnection();
try {
// 执行SQL语句,ArrayHandler,获取一个包含对应字段数据的数组
Object[] objects = queryRunner.query(connection, sql, new ArrayHandler());
// 将数组转为字符串并展示
System.out.println(Arrays.toString(objects));
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtils.close(connection);
}
}
}
【补充】使用 DbUtils 的 ArrayListHandler 获取包含对应多条数据的数组
// 处理符合JavaBean规范的类对象,能够将数据转为一个包含Object类型的数组的集合
class ArrayListHandler extends AbstractListHandler<Object[]> {}
案例代码
public class Demo5 {
@Test
public void testQueryOne() {
// 获取QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 准备SQL语句
String sql = "select * from student where id = 1";
// 获取连接
Connection connection = JdbcUtils.getConnection();
try {
// 执行SQL语句,ArrayHandler,获取一个包含对应字段数据的数组
Object[] objects = queryRunner.query(connection, sql, new ArrayHandler());
// 将数组转为字符串并展示
System.out.println(Arrays.toString(objects));
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtils.close(connection);
}
}
}
数据库连接池
概述
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
常见的数据库连接池
C3P0
DBCP
Druid【常用】
C3P0连接池的使用
导入jar包
mchange-commons-java-0.2.19.jar
c3p0-0.9.5.2.jar
配置文件
<!-- c3p0-config.xml需要存储于src目录下 -->
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/FC2020?useSSL=true&characterEncoding=UTF8</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<!--初始化申请的连接数量-->
<property name="initialPoolSize">5</property>
<!--最大的连接数量-->
<property name="maxPoolSize">10</property>
<!--超时时间-->
<property name="checkoutTimeout">3000</property>
</default-config>
<named-config name="otherc3p0">
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/student?useSSL=true</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">8</property>
<property name="checkoutTimeout">1000</property>
</named-config>
</c3p0-config>
【注意】此配置文件需要放在[src]()目录下,不需要手动编写,直接复制粘贴后修改数据库名和密码即可!!!
使用 C3P0 封装 JdbcUtilsOnC3P0工具类
public class JdbcUtilsOnC3P0 {
// 声明一个c3p0连接池
private static ComboPooledDataSource pool = new ComboPooledDataSource();
private static Connection connection = null;
private static Statement statement = null;
private static ResultSet resultSet = null;
/**
* 获取连接
*
* @return 返回数据库的连接
*/
public static Connection getConnection() {
try {
// 通过c3p0连接池获取连接
connection = pool.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
/*
* 重载关闭资源方法,以满足多种场景
*/
public static void close(Connection connection) {
close(resultSet, statement, connection);
}
public static void close(ResultSet resultSet) {
close(resultSet, statement, connection);
}
public static void close(Statement statement, Connection connection) {
close(resultSet, statement, connection);
}
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
案例代码
public class Demo {
@Test
public void testQuery() {
// 获取QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 通过C3P0连接池获取连接
Connection connection = JdbcUtilsOnC3P0.getConnection();
// 准备SQL语句
String sql = "select * from student";
try {
// 使用BeanListHandler执行SQL语句获取对应数据的集合
List<Student> list = queryRunner.query(connection, sql, new BeanListHandler<Student>(Student.class));
// 增强for循环遍历
for (Student student : list) {
System.out.println(student);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtilsOnC3P0.close(connection);
}
}
}
Druid 连接池的使用
导包
druid-1.0.9.jar
配置文件
# 文件名 druid.properties 存储在src目录下
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/FC2020?useSSL=true&characterEncoding=UTF-8
username=root
password=root
# 初始化数据库连接池容量
initialSize=5
# 最大容量
maxActive=20
# TimeOut 等待超时时间
maxWait=2000
【注意】此配置文件需要放在[src]()目录下,不需要手动编写,直接复制粘贴后修改数据库名和密码即可!!!
使用 Druid 封装JdbcUtilsOnDruid 工具类
public class JdbcUtilsOnDruid {
// 数据库源
private static DataSource dataSource;
private static Connection connection = null;
private static Statement statement = null;
private static ResultSet resultSet = null;
static {
try {
// 加载Properties文件
Properties properties = new Properties();
properties.load(new FileReader("./src/druid.properties"));
// 已经完成数据库连接池操作
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 返回数据库连接对象,连接失败返回null
*
* @return java.sql.Connection 数据库连接对象
*/
public static Connection getConnection() {
try {
// 通过数据源获取连接
connection = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
/*
* 重载关闭资源方法,以满足多种场景
*/
public static void close(Connection connection) {
close(resultSet, statement, connection);
}
public static void close(ResultSet resultSet) {
close(resultSet, statement, connection);
}
public static void close(Statement statement, Connection connection) {
close(resultSet, statement, connection);
}
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
案例代码
public class Demo {
@Test
public void testDruid() {
// 获取QueryRunner对象
QueryRunner queryRunner = new QueryRunner();
// 准备SQL语句
String sql = "select * from student";
// 从Druid连接池中获取连接
Connection connection = JdbcUtilsOnDruid.getConnection();
try {
// 使用BeanListHandler执行SQL语句并获取带有数据的集合
List<Student> list = queryRunner.query(connection, sql, new BeanListHandler<Student>(Student.class));
// 增强for循环遍历集合
for (Student student : list) {
System.out.println(student);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
JdbcUtilsOnDruid.close(connection);
}
}
}
【补充】常见数据库连接
-------------------------------oracle------------------
驱动:oracle.jdbc.driver.OracleDriver
URL:jdbc:oracle:thin:@machine_name:port:dbname
注:machine_name:数据库所在的机器的名称;
port:端口号,默认是1521
-------------------------------mysql-------------------
驱动:com.mysql.jdbc.Driver
URL:jdbc:mysql://machine_name:port/dbname
注:machine_name:数据库所在的机器的名称;
port:端口号,默认3306
------------------------------SQL Server---------------
驱动:com.microsoft.jdbc.sqlserver.SQLServerDriver
URL:jdbc:microsoft:sqlserver://<machine_name><:port>;DatabaseName=<dbname>
注:machine_name:数据库所在的机器的名称;
port:端口号,默认是1433
------------------------------DB2----------------------
驱动:com.ibm.db2.jdbc.app.DB2Driver
URL:jdbc:db2://<machine_name><:port>/dbname
注:machine_name:数据库所在的机器的名称;
port:端口号,默认是5000
-------------------------------------------------------