- JDBC学习笔记02
- 数据库连接池
- 传统获取Connection问题分析
- 基本介绍
- 数据库连接池种类
- c3p0使用
- Druid(德鲁伊)应用实例
- 配置文件
- 封装成工具类
- 测试
- Apache-DBUtils
- 分析一个问题
- 土方法解决
- 基本介绍
- 应用实例
- BasicDao-DAO和增删改查通用方法
- 基本说明
- 应用实例
-
传统的JDBC数据库连接使用 DriverManager来获取,每次向数据库建立连接的时候都要将Connection 加载到内存中,再验证IP地址,用户名和密码(0.05S~1s时间)。需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接 *** 作将占用很多的系统资源,容易造成服务器崩溃。
-
每一次数据库连接,使用完后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄 漏,最终将导致重启数据库。
-
传统获取连接的方式,不能控制创建的连接数量,如连接过多,也可能导致内存泄漏,MySQL崩溃。
-
解决传统开发中的数据库连接问题,可以采用数据库连接池技术(connection pool)。
-
预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。
-
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
-
当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中
-
JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方提供实现
-
C3PO数据库连接池,速度相对较慢,稳定性不错(hibernate, spring)
-
DBCP数据库连接池,速度相对c3p0较快,但不稳定
-
Proxool数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
-
BoneCP 数据库连接池,速度快
-
Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP、C3P0、Proxool优点于一身的数据库连接池
方式1:
//方式1:相关参数,在程序中指定user,url,password
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
//通过配置文件获取相关的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//给数据源comboPooledDataSource设置相关的参数
//连接管理是由comboPooledDataSource来管理
comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password);
//设置初始化连接数
comboPooledDataSource.setInitialPoolSize(10);
//最大连接数
comboPooledDataSource.setMaxPoolSize(50);
long start = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
Connection connection = comboPooledDataSource.getConnection();//从DataSource方法实现的
System.out.println("连接成功");
connection.close();//回收
}
long end = System.currentTimeMillis();
System.out.println(end-start);
方式2:
c3p0-config.xml
<c3p0-config>
<named-config name="purplesky">
<property name="driverClass">com.mysql.cj.jdbc.Driverproperty>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/db02property>
<property name="user">rootproperty>
<property name="password">123456property>
<property name="acquireIncrement">5property>
<property name="initialPoolSize">10property>
<property name="minPoolSize">5property>
<property name="maxPoolSize">50property>
<property name="maxStatements">5property>
<property name="maxStatementsPerConnection">2property>
named-config>
c3p0-config>
//方式2.使用配置文件的模板
public void testC3P0_02() throws SQLException {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("purplesky");
Connection connection = comboPooledDataSource.getConnection();
System.out.println("连接成功");
connection.close();
}
Druid(德鲁伊)应用实例
配置文件
druid.properties
#key=value
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db02?rewriteBatchedStatements=true
username=root
password=123456
#initial connection Size
initialSize=10
#min idle connection size
minIdle=5
#max active connection size
maxActive=50
#max wait time (5000 mil seconds)
maxWait=5000
//1.加入jar包
//2.加入配置文件druid.properties,放到src目录下
//3.创建Properties对象,读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\druid.properties"));
//4.创建一个指定参数的数据库连接池
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
Connection connection = dataSource.getConnection();
System.out.println("连接成功");
connection.close();
封装成工具类
JDBCUtilsByDruid
public class JDBCUtilsByDruid {
private static DataSource ds;
//在静态代码块完成ds初始化
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\druid.properties"));
ds = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Connection getConnection(){
try {
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//放回到连接池
public static void close(ResultSet set, Statement statement, Connection connection) {
try {
if (set != null) {
set.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
测试
@Test
public void testSelect() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet set = null;
String sql = "select * from actor where id = ?";
try {
connection = JDBCUtilsByDruid.getConnection();
System.out.println(connection.getClass());
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,2);
set = preparedStatement.executeQuery();
while (set.next()) {
int id = set.getInt("id");
String name = set.getString("name");
String sex = set.getString("sex");
Date borndate = set.getDate("borndate");
String phone = set.getString("phone");
System.out.println(id + "\t" + name + "\t" + sex + "\t" + borndate + "\t" + phone);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtilsByDruid.close(set, preparedStatement, connection);
}
}
@Test
public void testDML() {
Connection connection = null;
PreparedStatement preparedStatement = null;
String sql = "update actor set name = ? where id =?";
try {
connection = JDBCUtilsByDruid.getConnection();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "周星驰");
preparedStatement.setInt(2, 2);
preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtilsByDruid.close(null, preparedStatement, connection);
}
}
Apache-DBUtils
分析一个问题
- 关闭connection后,resultSet 结果集无法使用
- resultSet不利于数据的管理
public ArrayList<Actor> testSelectToArrayList() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet set = null;
String sql = "select * from actor where id = ?";
ArrayList<Actor> list = new ArrayList<>();
try {
connection = JDBCUtilsByDruid.getConnection();
System.out.println(connection.getClass());
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,2);
set = preparedStatement.executeQuery();
while (set.next()) {
int id = set.getInt("id");
String name = set.getString("name");
String sex = set.getString("sex");
Date borndate = set.getDate("borndate");
String phone = set.getString("phone");
list.add(new Actor(id,name,sex,borndate,phone));
}
System.out.println(list);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtilsByDruid.close(set, preparedStatement, connection);
}
return list;
}
基本介绍
- commons-dbutils是Apache组织提供的一个开源 JDBC工具类库,它是对JDBC的封装,使用dbutils能极大简化jdbc编码的工作量。
- QueryRunner类:该类封装了SQL的执行,是线程安全的。可以实现增、删、改、查、批处理使用
- QueryRunner类实现查询
- ResultSetHandler接口:该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式
ArrayHandler:把结果集中的第一行数据转成对象数组。
ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里
ColumnListHandler:将结果集中某一列的数据存放到List中。
KeyedHandler(name):将结果集中的每行数据都封装到Map里,再把这些map再存到一个map里,其key为指定的key。
MapHandler: 将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
应用实例
使用DBUtils+数据库连接池(德鲁伊)方式,完成对表的crud
date –> Date或String
char,varchar –> String
@Test
public void testQueryMany() throws SQLException {
//1.得到连接druid
Connection connection = JDBCUtilsByDruid.getConnection();
//2.使用DBUtils类和接口,先引入DBUtils相关的jar
//3.创建QueryRunner
QueryRunner queryRunner = new QueryRunner();
//4.执行相关的方法,返回ArrayList结果集
//query方法执行sql语句,得到resultSet--封装到ArrayList
//返回集合
//connection连接
//sql语句
//new BeanListHandler<>(Actor.class):在将resultSet-->Actor对象-->封装到ArrayList
//底层使用反射机制去获取Actor类的属性,然后进行封装
//1是传给?的,可以有多个值,是可变参数
//底层得到的resultSet会在query关闭,关闭PreparedStatement
//String sql = "select id,name,sex,phone,borndate from actor where id >= ?";
String sql = "select * from actor where id >= ?";
List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);
for (Actor actor : list) {
System.out.println(actor);
}
JDBCUtilsByDruid.close(null, null, connection);
}
@Test
//单行记录
public void testQuerySingle() throws SQLException {
Connection connection = JDBCUtilsByDruid.getConnection();
QueryRunner queryRunner = new QueryRunner();
String sql = "select id,name,sex,phone from actor where id = ?";
Actor actor = queryRunner.query(connection, sql, new BeanHandler<>(Actor.class), 2);
System.out.println(actor);
JDBCUtilsByDruid.close(null, null, connection);
}
@Test
//apache-dbUtils+druid完成查询结果是单行单列的情况
public void testScalar() throws SQLException {
Connection connection = JDBCUtilsByDruid.getConnection();
QueryRunner queryRunner = new QueryRunner();
String sql = "select name from actor where id = ?";
Object obj = queryRunner.query(connection, sql, new ScalarHandler(), 2);
System.out.println(obj);
JDBCUtilsByDruid.close(null, null, connection);
}
@Test
public void testDML() throws SQLException {
Connection connection = JDBCUtilsByDruid.getConnection();
QueryRunner queryRunner = new QueryRunner();
//String sql = "update actor set name = ? where id = ?";
//String sql = "insert into actor values(null,'林青霞','女','1966-10-10','116')";
String sql = "insert into actor values(null, ?, ?, ?, ?)";
//String sql = "delete from actor where id = ?)";
//返回值是受影响行数,失败0
//int affectedRow = queryRunner.update(connection, sql, "张三丰", 4);
int affectedRow = queryRunner.update(connection, sql, "林青霞", "女", "1966-10-10", "116");
if (affectedRow != 0) {
System.out.println("成功");
} else {
System.out.println("没有影响到表");
}
}
BasicDao-DAO和增删改查通用方法
apache-dbutils+Druid简化了JDBC开发,但还有不足:
- SQL语句是固定,不能通过参数传入,通用性不好,需要进行改进,更方便执行增删改查
- 对于select *** 作,如果有返回值,返回类型不能固定,需要使用泛型
- 将来的表很多,业务需求复杂,不可能只靠一个Java类完成
- 引出 BasicDAO
- DAO: data access object数据访问对象
- 这样的通用类,称为BasicDao,是专门和数据库交互的,即完成对数据库(表)的crud *** 作。在BaiscDao 的基础上,实现一张表对应一个Dao,更好的完成功能,比如 Customer表-customer.java类(javabean)-CustomerDao.java
- utils
- domain
- dao
- test
JDBCUtilsByDruid
public class JDBCUtilsByDruid {
private static DataSource ds;
//在静态代码块完成ds初始化
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\druid.properties"));
ds = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Connection getConnection(){
try {
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//放回到连接池
public static void close(ResultSet set, Statement statement, Connection connection) {
try {
if (set != null) {
set.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
BasicDAO
/**
* @author purplesky
* 其他DAO的父类
*/
public class BasicDAO<T> {
private QueryRunner qr = new QueryRunner();
//开发通用的dml方法,针对任意的表
public int update(String sql, Object... parameters) {
Connection connection = null;
try {
connection = JDBCUtilsByDruid.getConnection();
int update = qr.update(connection, sql, parameters);
return update;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtilsByDruid.close(null, null, connection);
}
}
//返回多个对象,多行查询结果
public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters) {
Connection connection = null;
try {
connection = JDBCUtilsByDruid.getConnection();
return qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtilsByDruid.close(null, null, connection);
}
}
//单行结果
public T querySingle(String sql, Class<T> clazz, Object... parameters) {
Connection connection = null;
try {
connection = JDBCUtilsByDruid.getConnection();
return qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtilsByDruid.close(null, null, connection);
}
}
//返回单值的方法
public Object queryScalar(String sql, Object... parameters) {
Connection connection = null;
try {
connection = JDBCUtilsByDruid.getConnection();
return qr.query(connection, sql, new ScalarHandler(), parameters);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtilsByDruid.close(null, null, connection);
}
}
}
ActorDAO
public class ActorDAO extends BasicDAO<Actor> {
//1.有BasicDAO的方法
//2.也可以编写特有的方法
}
测试
public class TestDAO_ {
@Test
public void testActorDAO() {
ActorDAO actorDAO = new ActorDAO();
List<Actor> actors = actorDAO.queryMulti("select id,name,sex,phone from actor where id >= ?", Actor.class, 1);
for (Actor actor : actors) {
System.out.println(actor);
}
//查询单行记录
Actor actor = actorDAO.querySingle("select id,name,sex,phone from actor where id = ?", Actor.class, 1);
System.out.println(actor);
//查询单行单列
Object o = actorDAO.queryScalar("select name from actor where id = ?", 6);
System.out.println(o);
//dml
int update = actorDAO.update("insert into actor values(null, ?, ?, ?, ?)", "张无忌", "男", "2000-11-11", "999");
System.out.println(update > 0 ? "执行成功":"没有影响表");
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)