Java之数据库连接封装成工具类,三个核心(DBUtils,QueryRunner,ResultSetHandler8个结果集)的使用和数据源DataSource(数据库连接池)
一.数据库连接封装成工具类
1.数据库连接封装成工具类的方法
第一种:不用把加载驱动的字符串和数据库地址,用户,密码写在代码的形式(更改地址,用户,密码等需要从代码中更改,不太方便):
这里需要用到静态代码块,因为驱动是只加载一次就可以.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/*
* 封装获取连接工具
*/
public class JDBCUtil1 {
// 声明连接
private static Connection connection;
// 注册驱动
static{
try {
// 只注册一次
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
// 直接抛个运行时异常
throw new RuntimeException("注册驱动失败");
}
}
// 私有化构造方法
private JDBCUtil1() {
}
// 获取连接方法
public static Connection getConnection(){
// 数据库地址
String url = "jdbc:mysql://localhost:3306/klljdbc01";
// 数据库账号
String user = "root";
// 数据库密码
String password = "123456";
// 获取连接
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
// 直接抛个运行时异常
throw new RuntimeException("数据库连接失败");
}
return connection;
}
// 关闭资源
public static void myClose(Connection connection, ResultSet resultSet,Statement statement){
// 关闭资源
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (resultSet != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
第二种:使用从文本读入的方式,环境变了,更改地址用户密码等直接从文本更改.
注意:文本只能创建在src文件夹下
此处使用到了通过类加载器直接获取bin文件夹下的文件的字节流方法
本类类名.class.getClassLoader().getResourceAsStream("文件名");
文件(文件名:db.properties)内容:
/*
* 读取文件的数据库连接工具类
*/
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtil2 {
private static Connection connection;
private static String driverClass;
private static String url;
private static String user;
private static String password;
private JDBCUtil2() {
}
static{
// 只读一次文件
readFile();
// 只注册驱动一次
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// 运行时异常
throw new RuntimeException("加载驱动异常");
}
}
// 读文件方法
public static void readFile() {
// 通过类加载器直接获取bin文件夹下的文件的字节流
// 获取类加载器
InputStream ist = JDBCUtil2.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
try {
properties.load(ist);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
driverClass = properties.getProperty("driverClass");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
}
// 获取连接
public static Connection getConnection() {
try {
// 获取连接
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// 抛出运行时异常
throw new RuntimeException("连接失败");
}
return connection;
}
// 关闭方法
public static void myClose(Connection connection, Statement statement, ResultSet resultSet) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (statement != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (resultSet != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2.查询记录封装成方法
数据库sort表对应的实体类.
- 表中字段 就是实体类中成员变量
- 为了表示null值,一般把基本数据类型声明成包装类
sort表:
sort实体类:
public class Sort {
private Integer sid;
private String sname;
private Double sprice;
private String sdesc;
// 构造方法
public Sort() {
super();
// TODO Auto-generated constructor stub
}
public Sort(Integer sid, String sname, Double sprice, String sdesc) {
super();
this.sid = sid;
this.sname = sname;
this.sprice = sprice;
this.sdesc = sdesc;
}
// set/get方法
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Double getSprice() {
return sprice;
}
public void setSprice(Double sprice) {
this.sprice = sprice;
}
public String getSdesc() {
return sdesc;
}
public void setSdesc(String sdesc) {
this.sdesc = sdesc;
}
// 重写tostring方法
@Override
public String toString() {
return "[sid=" + sid + ", sname=" + sname + ", sprice=" + sprice + ", sdesc=" + sdesc + "]";
}
}
工具类的使用代码如下(打印全表信息):
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/*
* 测试
*/
public class Demo01 {
public static void main(String[] args) throws Exception {
// 获取连接
Connection connection = JDBCUtil2.getConnection();
// 获取sql执行对象
String sql = "select * from sort";
PreparedStatement statement = connection.prepareStatement(sql);
// 获取sql执行语句
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
// 创建对象
Sort sort = new Sort();
sort.setSid(resultSet.getInt("sid"));
sort.setSname(resultSet.getString("sname"));
sort.setSdesc(resultSet.getString("sdesc"));
sort.setSprice(resultSet.getDouble("sprice"));
System.out.println(sort);
}
JDBCUtil2.myClose(connection, statement, resultSet);
}
}
运行结果:
二.三个核心
Commons-dbutils(提供快速操作的数据库方法)
1.DBUtils
- 提供了 closeQuietly(Connection conn)方法
- 安静的关闭 不用你来处理异常
2.DataSource
- 查询方法
- query(Connection conn, String sql, ResultSetHandler rsh, Object… params)
- 参数1:数据库的连接对象
- 参数2:sql语句(可以使用?占位符)
- 参数3:查询后得到的结果集(可以选用不同类型的结果集)
- 参数4:替换sql语句的占位符
- 更新方法(插入 删除 修改)
- pdate(Connection conn, String sql, Object… params)
DataSource的查询和更新方法使用如下:
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
/*
* Commons-dbutils(提供快速操作的数据库方法)
* 三个核心
* 1.DBUtils
* 提供了 closeQuietly(Connection conn)方法
* 安静的关闭 不用你来处理异常
* 2.QueryRunner
* 查询方法
* query(Connection conn, String sql,
* ResultSetHandler<T> rsh, Object... params)
* 参数1:数据库的连接对象
* 参数2:sql语句(可以使用?占位符)
* 参数3:查询后得到的结果集(可以选用不同类型的结果集)
* 参数4:替换sql语句的占位符
* 更新方法(插入 删除 修改)
* update(Connection conn, String sql, Object... params)
* /
public class Kll {
public static void main(String[] args) throws Exception {
// 调用方法: 是插入数据
fun1();
// 调用方法 删除id=3的数据
fun2();
// 修改id=8 为 毛毯 200 还不错呀
Connection connection = JDBCUtil2.getConnection();
QueryRunner runner = new QueryRunner();
String sql = "update sort set sname=?,sprice=?,sdesc=? where sid=?";
Object[] param = {"毛毯", 200 , "还不错呀", 8};
int update = runner.update(connection, sql, param);
System.out.println(update);
// 关闭资源
DbUtils.closeQuietly(connection);
}
public static void fun2() throws SQLException {
// 删除id = 3
QueryRunner runner = new QueryRunner();
Connection connection = JDBCUtil2.getConnection();
String sql = "delete from sort where sid=? ";
// 结束影响的行数
int update = runner.update(connection, sql, 3);
System.out.println(update);
// 关闭资源
DbUtils.closeQuietly(connection);
}
public static void fun1() throws SQLException {
// 插入
// 创建查询对象
QueryRunner runner = new QueryRunner();
Connection conn = JDBCUtil2.getConnection();
String sql = "insert into sort values (null,?,?,?)";
// 创建数组
Object[] params = {"发卡",12.5,"包邮"};
int i = runner.update(conn, sql, params);
// 打印受影响的行数
System.out.println(i);
int update = runner.update(conn, sql, "水桶",23.5,"包邮");
System.out.println(update);
// 关闭资源
DbUtils.closeQuietly(conn);
}
}
3.ResultSetHandler(提供8个结果集供人使用)
- ArrayHandler :默认返回查询的第一条数据,并且把该数据放入object数组中返回.
- ArrayListHandler:可以返回多条记录,并且每一条记录放在object数组中, 然后把多条记录又放在list集合中返回.
- BeanHandler:(查询的是多条数据,只返回第一条)
- 注意:要封装的对象必须符合Javabean规范(有set,get方法,有参无参构造方法)
- ** BeanListHandler:返回保存好对象的list集合.(常用)**
* 注意和BeanHandler的要求一样. - ColumnListHandler:默认返回数据库中第一列数据的集合,也可以传入参数字段名或者列的顺序.
- ScalarHandler:获取聚合函数返回的数据 返回的是long型.
- MapHandler::默认返回查询的map集合,此集合是封装的第一条数据的字段名和对应的值;集合中,key值是字段名,value是字段对应的值.
- MapListHandler:是把每一条记录的字段名和对应的值放在map集合中,然后再把map集合放在list集合中,返回list集合.
以下是8个结果集的应运:
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
/*
* 查询的8个结果集
ArrayHandler
ArrayListHandler
BeanHandler
BeanListHandler
ColumnListHandler
ScalarHandler
MapHandler
MapListHandler
*/
public class Kll {
public static void main(String[] args) throws SQLException {
String sql = "select * from sort";
QueryRunner runner = new QueryRunner();
Connection conn = JDBCUtil2.getConnection();
//fun1(sql, runner, conn);
//fun2(sql, runner, conn);
//fun3(sql, runner, conn);
//fun4(sql, runner, conn);
//fun5(sql, runner, conn);
//fun6(runner, conn);
fun7(sql, runner, conn);
// MapListHandler
List<Map<String,Object>> query2 = runner.query(conn, sql, new MapListHandler());
for (Map<String, Object> map : query2) {
for (String key : map.keySet()) {
System.out.print(key + " " + map.get(key));
}
System.out.println();
}
// 关闭
DbUtils.closeQuietly(conn);
}
public static void fun7(String sql, QueryRunner runner, Connection conn) throws SQLException {
// MapHandler
Map<String, Object> map = runner.query(conn, sql, new MapHandler());
System.out.println(map);
}
public static void fun6(QueryRunner runner, Connection conn) throws SQLException {
// ScalarHandler
//获取聚合函数返回的数据 返回的是long型
String sql1 = "select count(*) from sort";
Number number = runner.query(conn, sql1, new ScalarHandler<Long>());
System.out.println(number.longValue());
}
public static void fun5(String sql, QueryRunner runner, Connection conn) throws SQLException {
// ColumnListHandler
// 默认返回数据库中第一列数据的集合
// 可以传入参数字段名或者列的顺序
List<Object> list2 = runner.query(conn, sql, new ColumnListHandler<>());
for (Object object : list2) {
System.out.println(object);
}
}
public static void fun4(String sql, QueryRunner runner, Connection conn) throws SQLException {
// BeanListHandler(常用)
// 返回保存好对象的list集合
List<Sort> list = runner.query(conn, sql, new BeanListHandler<Sort>(Sort.class));
for (Sort sort : list) {
System.out.println(sort);
}
}
public static void fun3(String sql, QueryRunner runner, Connection conn) throws SQLException {
// BeanHandler(查询的是多条数据,只返回第一条)
// 注意:要封装的对象必须符合Javabean规范(有set,get方法,有参无参构造方法)
Sort query = runner.query(conn, sql, new BeanHandler<Sort>(Sort.class));
System.out.println(query);
}
public static void fun2(String sql, QueryRunner runner, Connection conn) throws SQLException {
// ArrayListHandler
// 可以返回多条记录,并且每一条记录放在object数组中
// 然后把多条记录又放在list集合中返回
List<Object[]> query = runner.query(conn, sql, new ArrayListHandler());
for (Object[] objects : query) {
for (Object object : objects) {
System.out.print(object + " ");
}
System.out.println();
}
}
// 测试ArrayHandler
// 默认返回查询的第一条数据,并且把该数据放入object数组中返回
public static void fun1(String sql, QueryRunner runner, Connection conn) throws SQLException {
Object[] query = runner.query(conn, sql, new ArrayHandler());
System.out.println(Arrays.toString(query));
}
}
三.数据源DataSource(数据库连接池)
-
DataSource 数据源(数据库连接池)
-
查询时 创建和销毁连接 耗费资源
-
使用数据库连接池可以解决这个问题
-
查询时 会从数据库连接池中 找一个空闲的连接 去查询数据库
-
查询完毕后 不会销毁该连接 会重新放入连接池中 等待下一次使用
-
Java也提供一套规范来处理数据库连接池问题
-
javax.sql DataSource
-
这套规范也是厂商来实现 我们只要使用实现好的方法就好
-
连接池:DBCP C3P0
-
使用DBCP需要导入两个jar包
-
commons-pool-1.5.6.jar
-
commons-dbcp-1.4.jar
1.直接使用代码如下:
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;
public class Kll {
public static void main(String[] args) throws SQLException {
// 创建数据库连接池
BasicDataSource dataSource = new BasicDataSource();
// 基础设置(地址 账号 密码)
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/klljdbc01");
dataSource.setUsername("root");
dataSource.setPassword("123456");
// 获取连接
Connection connection = dataSource.getConnection();
}
}
封装成工具类的方法下章继续.