6.数据库连接池&DBUtils
1.数据库连接池
1.连接池的概念
- 连接池就是存放连接的池子,用来管理连接。
- 好处:可减少重复的使用连接,减少资源浪费(不用每次创建、释放连接)
2.如何使用数据库连接池
- java为数据库提供了公共的接口:java.sql.DataSource,具体的实现由驱动程序供应商实现。
- 常见的有DBCP连接池、C3P0连接池、Druid连接池
3.DBCP连接池
- DBCP是Apache成员之一,是一个开源连接池(tomcat内置连接池)
- 每创建一个项目要导入相应的jar包
1.编写工具类
- java提供了连接池接口:DataSource;
- DBCP提供了实现类:BasicDataSource;
- 工具类代码:
public class DBCPUtils {
//1.定义常量 保存数据库连接信息
public static final String DRIVERNAEM="com.mysql.jdbc.Driver";
public static final String URL="jdbc:mysql://localhost:3306/db5?characterEncoding=UTF-8";
public static final String USERNAME="root";
public static final String PASSWORD="123456";
//2.创建连接对象(由DBCP提供的实现类)
public static BasicDataSource dataSource=new BasicDataSource();
//3.使用静态代码块进行配置
static {
dataSource.setDriverClassName(DRIVERNAEM);
dataSource.setUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
}
//4.获取连接的方法
public static Connection getConnection() throws SQLException {
//从连接池中获取
Connection connection=dataSource.getConnection();
return connection;
}
//5.释放资源
public static void close(Connection con, Statement statement){}
public static void close(Connection con, Statement statement, ResultSet resultSet){}
-
测试类代码:
public class TestDBCP { /** * 测试DBCP连接池 * @param args */ public static void main(String[] args) throws SQLException { //1.获取连接 Connection connection= DBCPUtils.getConnection(); //2.获取语句执行对象 Statement statement = connection.createStatement(); //3.SQL语句执行 String sql="select ename from employee"; ResultSet resultSet = statement.executeQuery(sql); //处理结果集 while(resultSet.next()){ String ename=resultSet.getString("ename"); System.out.println(ename); } //5.释放资源 DBCPUtils.close(connection,statement,resultSet); } }
2.DBCP的配置项
driverClassName | 数据库驱动名称 |
---|---|
url | 数据库地址 |
username | 用户名 |
password | 密码 |
4.C3P0连接池
- 开源的连接池。目前支持它的开源项目有:Spring、Hibernate
- C3P0的核心工具类:ComboPooledDataSource
- 导入相关架包至myjar文件夹。
1.导入配置文件xml
-
将写好的配置文件放入src。建议创建一个resource文件夹(专门存放资源文件)
2.编写C3P0工具类
public class C3P0Utils {
//1.创建连接池对象,使用配置文件(无参使用xml中默认配置方法)
public static ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql");
//2.获得连接方法
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
//3.关闭资源
public static void close(Connection con, Statement statement){}
public static void close(Connection con, Statement statement, ResultSet resultSet){}
}
5.Druid连接池
- Druid(德鲁伊)是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。
- 同样需要导入相关jar包
1.导入配置文件(properties)格式
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db5?characterEncoding=UTF-8
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
#### 2.编写Druid工具类
+ 获取连接池对象
+ 通过工厂来获取: DruidDataSourceFactory类的createDataSource方法;
+ createDataSource(Properties p) 方法参数是一个属性集对象
```java
public class DruidUtils {
//1.定义成员变量
public static DataSource dataSource;
//2.静态代码块
static {
try {
//3.创建属性集对象
Properties p=new Properties();
//4.加载配置文件。Druid连接池不能主动加载配置文件,需要指定文件。
InputStream inputStream = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
//5.使用Propreties对象的load方法,从字节流中读取配置文件
p.load(inputStream);
//6.使用工厂类获取连接池对象
dataSource = DruidDataSourceFactory.createDataSource(p);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接方法
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
//获取Druid连接池对象的方法 给QueryRunner使用
public static DataSource getDataSource(){
return dataSource;
}
//释放资源……
2.DBUtils工具类(重点)
1.DBUtils简介
- Commons DBUtils是Apache提供的一个对JDBC进行简单封装的开源工具类库,可以简化JDBC程序的开发。
- 同样导入相关jar包.(commons-dbutils-1.6.jar)
2.核心功能
- QueryRunner 中提供对sql语句操作的API
- ResultSetHandler接口,用于定义select操作后,怎样封装结果集
- DbUtils类,他就是一个工具类,定义了关闭资源与事务处理相关方法.
3.JavaBean组件
- JavaBenn就是一个实体类,开发中通常用于封装数据。有以下特点:
- 实现序列化接口,Serializable
- 提供空参构造
- 私有化字段
- 提供getter和setter方法
- 创建Employee类和数据库的employee表对应
- :可以创建一个entity(实体)包,存放JavaBean
4.QueryRunner核心类
1.构造方法
- QueryRunner() //手动
- QueryRunner(DataSource ds) ,提供连接池对象,DBUtils底层自动维护连接connection
2.常用方法
-
update(Connection conn, String sql, Object… params) ,用来完成表数据的增加、删除、更新操作
-
query(Connection conn, String sql, ResultSetHandler rsh, Object… params) ,用来完成表 数据的查询操作
-
参数 说明 Connection conn 数据库连接对象, 自动模式创建QueryRun 可以不传 ,手动模式必须传递 String sql 占位符形式的SQL ,使用 ? 号占位符 Object…param Object类型的 可变参,用来设置占位符上的参数
步骤 1.创建QueryRunner(手动或自动) 2.占位符方式 编写SQL 3.设置占位符参数 4.执行
3.代码示例(DML)
//增加
@Test
public void testInsert() throws SQLException {
//1.手动创建QueryRunner
QueryRunner qr=new QueryRunner();
//2.编写sql
String sql="insert into employee values(?,?,?,?,?,?)";
//3.设置占位符参数
Object[] parm={null,"张三",20,"女",10000,"2021-1-19"};
//4.执行update方法
Connection connection = DruidUtils.getConnection();
int i = qr.update(connection, sql, parm);
//5.释放资源
//connection.close();
DbUtils.close(connection);
}
//修改
@Test
public void testUpdate() throws SQLException {
//1.自动创建QueryRunner
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
//2.编写sql
String sql = "update employee set salary=? where ename=?";
//3.设置占位符参数
Object[] parm = {0, "张三"};
//4.执行update方法
Connection connection = DruidUtils.getConnection();
int i = qr.update(sql, parm);
//5.释放资源
DbUtils.close(connection);
}
4.QueryRunner实现查询操作
query(Connection conn, String sql, ResultSetHandler rsh, Object... params)
ResultSetHandler接口的常见实现类:
ResultSetHandler 实现类 | 说明 |
---|---|
ArrayHandler | 将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值 |
ArrayListHandler | 将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。 |
BeanHandler | 将结果集中第一条记录封装到一个指定的javaBean中. |
BeanListHandler | 将结果集中每一条记录封装到指定的javaBean中,再将这些javaBean在封装到List 集合中 |
MapHandler | 将结果集中第一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值 |
ColumnListHandler | 将结果集中指定的列的字段值,封装到一个List集合中 |
ScalarHandler | 用于封装单个数据(返回long类型) |
- ResultSetHandler 常用实现类
- :query([Connection con],String sql, handler ,Object[] param) 。自动模式创建QueryRunner, 执行查询
5.代码示例
@Test //查询id为5的记录,封装到数组中 [ArrayHandler]
public void testFindById() throws SQLException {
//1.创建QueryRunner
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
//2.编写sql
String sql = "select * from employee where eid=?";
//3.执行
Object[] query = qr.query(sql, new ArrayHandler(), 5);
System.out.println(Arrays.toString(query));
}
@Test //查询薪资大于 3000 的所员工信息,封装到JavaBean中再封装到List集合中[BeanListHandler]
public void testFindBySalary() throws SQLException {
//1.创建QueryRunner
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
//2.编写sql
String sql = "select * from employee where salary>?";
//3.执行
List<Employee> query = qr.query(sql, new BeanListHandler<Employee>(Employee.class), 300);
for (Employee e : query) {
System.out.println(e);
}
}
//查询姓名是 张百万的员工信息,将结果封装到Map集合中[MapHandler]
@Test
public void testFindByName() throws SQLException {
//1.创建QueryRunner
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
//2.编写sql
String sql = "select * from employee where ename=?";
//3.执行
Map<String, Object> query = qr.query(sql, new MapHandler(), "李白");
//4. 返回键值对
Set<Map.Entry<String, Object>> entries = query.entrySet();
System.out.println(entries);
}
@Test //查询指定列的的字段值,封装到一个List集合中[ColumnListHandler]
public void testFindName() throws SQLException {
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
String sql = "select ename from employee";
List<String> query = qr.query(sql, new ColumnListHandler<String>());
for (String e : query) {
System.out.println(e);
}
}
3.数据库批处理
- 一次操作执行多条SQL语句,提高效率
- Mysql默认关闭批处理,要在url加个参数打开(rewriteBatchedStatements=true)
- Statement和PreparedStatement都支持批处理操作
方法 | 说明 |
---|---|
void addBatch() | 将给定的 SQL 命令添加到此 Statement 对象的当前命令列表中。 |
int[] executeBatch() | 提交命令值数据库执行,成功返回一个数组(受影响的行数) |
Connection connection = DruidUtils.getConnection();//连接
//获取语句执行平台
String sql="insert into testBatch(uname) values(?)";
PreparedStatement preparedStatement =connection.prepareStatement(sql);
for (int i = 0; i < 10000; i++) {
preparedStatement.setString(1,"小张"+i);
preparedStatement.addBatch();
}
int[] ints = preparedStatement.executeBatch();
4.Mysql元数据
- 除表以外的数据都是元数据,分为以下三类:
- 查询结构信息
- 数据库和数据表的信息
- MYSQL服务器信息
1.使用JDBC获取元数据
- JDBC中描述元数据的类:
元数据类 | 作用 |
---|---|
DatabaseMetaData | 描述数据库的元数据对象(connection调用) |
ResultSetMetaData | 描述结果集的元数据对象(prepareStatement调用) |
- 获取元数据对象的方法:getMetaData ()
2.DatabaseMetaData常用方法
方法说明 |
---|
getURL() : 获取数据库的URL |
getUserName(): 获取当前数据库的用户名 |
getDatabaseProductName(): 获取数据库的产品名称 |
isReadOnly(): 判断数据库是否只允许只读 true 代表只读 |
3.ResultSetMetaData方法
方法说明 |
---|
getColumnCount() : 当前结果集共有多少列 |
getColumnName(int i) : 获取指定列号的列名, 参数是整数 从1开始 |
getColumnTypeName(int i): 获取指定列号列的类型, 参数是整数 从1开始 |
roductName(): 获取数据库的产品名称 |
| isReadOnly(): 判断数据库是否只允许只读 true 代表只读 |
3.ResultSetMetaData方法
方法说明 |
---|
getColumnCount() : 当前结果集共有多少列 |
getColumnName(int i) : 获取指定列号的列名, 参数是整数 从1开始 |
getColumnTypeName(int i): 获取指定列号列的类型, 参数是整数 从1开始 |