第一章 使用连接池重写工具类
连接池原理
连接池理解为存放多个连接的集合。
目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能
编写标准的数据源(规范)
Java为数据库连接池提供了公共的接口:javax.sql.DataSource
各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
常见的连接池:C3P0、DBCP。
常用的数据源配置
C3P0连接池 – 开源免费
目前使用它的开源项目有:Spring、Hibernate等。
使用C3P0连接池需要导入jar包,C3P0使用时还需要添加配置文件“c3p0-config.xml”
连接池的好处:
当使用java.sql中提供的api创建数据库连接时候,需要耗费很大的资源,要进行用户名密码数据库连接验证等,即耗费资源也耗费时间。如果在程序中,每次需要访问数据库时候,都进行数据库连接,那么势必会造成性能低下;同时,如果用户失误忘记释放数据库连接,会导致资源的浪费等。而数据库连接池就是解决该问题,通过管理连接池中的多个连接对象(connection),实现connection重复利用。从而,大大提高了数据库连接方面的性能。
连接池的功能:
负责创建,管理,释放,分配数据库连接即(connection)。首先,负责创建相应数目的数据库连接对象(connection),并存放到数据库连接池中。当用户请求数据库连接时,该连接池负责分配某个处于空闲状态的数据库连接对象;当用户发出释放该数据库连接时,该连接池负责将该连接对象重新设置为空闲状态,以便被别的请求重复利用。同时数据库连接池负责检查(空闲时间>最大空闲时间)的数据库连接,并释放。
自定义连接池
第一步:创建连接池实现(数据源),并实现接口javax.sql.DataSource,因为我们只使用该接口中的getConnection()方法供外界使用
第二步:提供一个集合,用于存放连接,因为移除/添加操作过多,所以选择LinkedList,提高效率
第三步:之后程序如果需要连接,则直接调用实现类的getConnection(),本方法将从连接池(容器List)获取连接,为了保证当前连接只给一个线程使用,所以我们需要将连接先从连接池中移除
第四步:当用户使用完连接,释放资源时,将连接重新归还到连接池中
package cn.itcast.demo.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;
import javax.sql.DataSource;
import cn.itcast.demo.JDBCUtils_V3;
/**
* 自定义连接池
* @author 小强
*
*/
public class MyDataSource implements DataSource{
//1.创建1个容器用于存储Connection对象
private static LinkedList<Connection> pool = new LinkedList<Connection>();
//2.创建5个连接放到容器中去
static{
for(int i = 0; i < 5; i++){
Connection conn = JDBCUtils_V3.getConnection();
pool.add(conn);
}
}
@Override
public Connection getConnection() throws SQLException {
Connection conn = null;
//3.使用前先判断
if(pool.size() == 0){
//4.池子里面没有,我们再创建一些
for(int i = 0; i < 5; i++){
conn = JDBCUtils_V3.getConnection();
pool.add(conn);
}
}
//5.从池子里面获取一个连接对象Connection
conn = pool.remove(0);
return conn;
}
/**
* 归还连接对象到连接池中去
*/
public void backConnection(Connection conn){
pool.add(conn);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
}
使用
package cn.itcast.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import javax.sql.DataSource;
import org.junit.Test;
import cn.itcast.demo.JDBCUtils_V3;
import cn.itcast.demo.DataSource.MyDataSource;
import cn.itcast.demo.DataSource.MyDataSource1;
public class TestMyDataSource {
/**
* 添加用户
* 使用改造过的Connection
*/
@Test
public void testAddUser1(){
Connection conn = null;
//import java.sql.PreparedStatement;
PreparedStatement pstmt = null;
//1.创建自定义连接池对象
DataSource dataSource = new MyDataSource1();
try {
//2.从池子中获取连接
conn = dataSource.getConnection();
String sql = "insert into newuser values(null,?,?)";
//3.必须在自定义的Connection类中重写prepareStatement方法
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "王1二");
pstmt.setString(2, "234");
int rows = pstmt.executeUpdate();
if(rows > 0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
//3.归还给连接池
//dataSource.backConnection(conn);
JDBCUtils_V3.release(conn, pstmt, null);
}
}
/**
* 添加用户
*/
@Test
public void testAddUser(){
Connection conn = null;
//import java.sql.PreparedStatement;
PreparedStatement pstmt = null;
//1.创建自定义连接池对象
MyDataSource dataSource = new MyDataSource();
try {
//2.从池子中获取连接
conn = dataSource.getConnection();
String sql = "insert into newuser values(null,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "王二");
pstmt.setString(2, "234");
int rows = pstmt.executeUpdate();
if(rows > 0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
//3.归还给连接池
dataSource.backConnection(conn);
JDBCUtils_V3.release(null, pstmt, null);
}
}
}
自定义连接池:方法增强
为什么需要增强?
自定义连接池中存在严重的问题,用户调用getConnection()获得连接后,必须使用release()方法进行连接的归还,如果用户调用conn.close()将连接真正的释放,连接池中出现无连接可用。
因此就希望,即使调用了close()方法,连接仍归还给连接池。close()方法原有功能释放资源时,期望功能:将当前及连接归还连接池。说明close()方法没有我们希望的功能,因此需要对close()方法进行增强,从而实现将连接归还给连接池的功能。
都有哪些方法增强的方法?
选用装饰者设计模式进行close()方法的增强:
代码实现:
使用装饰者设计模式增强close()方法 :MyConnection
package cn.itcast.demo.DataSource;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
/**
* 装饰者设计模式
* @author 小强
*
*/
//1.实现同一个借口Connection
public class MyConnection implements Connection{
//3.定义一个变量
private Connection conn;
private LinkedList<Connection> pool;
//2.编写一个构造方法(参数使用了面向对象的多态特性)
public MyConnection(Connection conn,LinkedList<Connection> pool){
this.conn = conn;
this.pool = pool;
}
@Override
//增强的方法
public void close() throws SQLException {
pool.add(conn);
}
/**
* 此方法必须必须覆盖
*/
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return conn.prepareStatement(sql);
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public Statement createStatement() throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return null;
}
@Override
public String nativeSQL(String sql) throws SQLException {
return null;
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
}
@Override
public boolean getAutoCommit() throws SQLException {
return false;
}
@Override
public void commit() throws SQLException {
}
@Override
public void rollback() throws SQLException {
}
@Override
public boolean isClosed() throws SQLException {
return false;
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
return null;
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
}
@Override
public boolean isReadOnly() throws SQLException {
return false;
}
@Override
public void setCatalog(String catalog) throws SQLException {
}
@Override
public String getCatalog() throws SQLException {
return null;
}
@Override
public void setTransactionIsolation(int level) throws SQLException {
}
@Override
public int getTransactionIsolation() throws SQLException {
return 0;
}
@Override
public SQLWarning getWarnings() throws SQLException {
return null;
}
@Override
public void clearWarnings() throws SQLException {
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return null;
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
return null;
}
@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
}
@Override
public void setHoldability(int holdability) throws SQLException {
}
@Override
public int getHoldability() throws SQLException {
return 0;
}
@Override
public Savepoint setSavepoint() throws SQLException {
return null;
}
@Override
public Savepoint setSavepoint(String name) throws SQLException {
return null;
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
}
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return null;
}
@Override
public Clob createClob() throws SQLException {
return null;
}
@Override
public Blob createBlob() throws SQLException {
return null;
}
@Override
public NClob createNClob() throws SQLException {
return null;
}
@Override
public SQLXML createSQLXML() throws SQLException {
return null;
}
@Override
public boolean isValid(int timeout) throws SQLException {
return false;
}
@Override
public void setClientInfo(String name, String value) throws SQLClientInfoException {
}
@Override
public void setClientInfo(Properties properties) throws SQLClientInfoException {
}
@Override
public String getClientInfo(String name) throws SQLException {
return null;
}
@Override
public Properties getClientInfo() throws SQLException {
return null;
}
@Override
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
return null;
}
@Override
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
return null;
}
@Override
public void setSchema(String schema) throws SQLException {
}
@Override
public String getSchema() throws SQLException {
return null;
}
@Override
public void abort(Executor executor) throws SQLException {
}
@Override
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
}
@Override
public int getNetworkTimeout() throws SQLException {
return 0;
}
}
自定义连接池代码(close()增强):MyDataSource1
package cn.itcast.demo.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;
import javax.sql.DataSource;
import cn.itcast.demo.JDBCUtils_V3;
/**
* 自定义连接池
* @author 小强
*
*/
public class MyDataSource1 implements DataSource{
//1.创建1个容器用于存储Connection对象
private static LinkedList<Connection> pool = new LinkedList<Connection>();
//2.创建5个连接放到容器中去
static{
for(int i = 0; i < 5; i++){
Connection conn = JDBCUtils_V3.getConnection();
//放入池子中Connection对象已经被改造了
MyConnection myconn = new MyConnection(conn, pool);
pool.add(myconn);
}
}
@Override
public Connection getConnection() throws SQLException {
Connection conn = null;
//3.使用前先判断
if(pool.size() == 0){
//4.池子里面没有,我们再创建一些
for(int i = 0; i < 5; i++){
conn = JDBCUtils_V3.getConnection();
//放入池子中Connection对象已经被改造了
MyConnection myconn = new MyConnection(conn, pool);
pool.add(myconn);
}
}
//5.从池子里面获取一个连接对象Connection
conn = pool.remove(0);
return conn;
}
/**
* 归还连接对象到连接池中去
*/
public void backConnection(Connection conn){
pool.add(conn);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
}
JDBC连接和释放资源代码:JDBCUtils_V3
package cn.itcast.demo;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import java.util.ResourceBundle;
/**
* 提供获取连接和释放资源的方法
* @author 小强
*
*/
public class JDBCUtils_V3 {
private static String driver;
private static String url;
private static String username;
private static String password;
/**
* 静态代码块加载配置文件信息
*/
static{
try {
//1.通过当前类获取类加载器
ClassLoader classLoader = JDBCUtils_V3.class.getClassLoader();
//2.通过类加载器的方法获取一个输入流
InputStream is = classLoader.getResourceAsStream("db.properties");
//3.创建一个properties对象
Properties props = new Properties();
//4.加载输入流
props.load(is);
//5.获取相关参数的值
driver = props.getProperty("driver");
url = props.getProperty("url");
username = props.getProperty("username");
password = props.getProperty("password");
} catch (IOException e) {
System.out.println(e);
}
}
/**
* 获取连接
* @return
*/
public static Connection getConnection(){
Connection conn = null;
try {
//1.注册驱动
Class.forName(driver);
//2.获取连接对象
conn = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
System.out.println(e);
}
return conn;
}
public static void release(Connection conn,PreparedStatement pstmt,ResultSet rs){
if(rs != null)
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(pstmt != null)
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(conn != null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
properties配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/web08?useUnicode=true&characterEncoing=utf8
username=root
password=123
测试代码:
/**
* 添加用户
* 使用改造过的Connection
*/
@Test
public void testAddUser1(){
Connection conn = null;
//import java.sql.PreparedStatement;
PreparedStatement pstmt = null;
//1.创建自定义连接池对象
DataSource dataSource = new MyDataSource1();
try {
//2.从池子中获取连接
conn = dataSource.getConnection();
String sql = "insert into newuser values(null,?,?)";
//3.必须在自定义的Connection类中重写prepareStatement方法
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "王1二");
pstmt.setString(2, "234");
int rows = pstmt.executeUpdate();
if(rows > 0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
//3.归还给连接池
//dataSource.backConnection(conn);
JDBCUtils_V3.release(conn, pstmt, null);
}
}
C3P0连接池(C3P0也是目前使用最多的)
要记得导入架包
使用c3p0时要导入配置文件c3p0-config.xml,位置是在src下
各项配置的含义
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:///web08</property>
<property name="user">root</property>
<property name="password">123</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<named-config name="itheima">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///web08</property>
<property name="user">root</property>
<property name="password">123</property>
</named-config>
</c3p0-config>
这里的xml有俩个配置,一个是默认配置,一个是通过名称调用的配置
ComboPooledDataSource dataSource = new ComboPooledDataSource();
ComboPooledDataSource dataSource = new ComboPooledDataSource(“itheima”);
没有参数的就是调用默认配置,有参数的就是调用有名字的配置
这里的话主要是使用dataSource.getConnection()来给程序使用获取连接
我们可以将其书写成一个工具类,方便使用,减少主程序书写时的代码量
自定义工具类(C3P0Utils)
package cn.itcast.demo;
import java.sql.Connection;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Utils {
private static ComboPooledDataSource dataSource = new ComboPooledDataSource("itheima");
public static DataSource getDataSource(){
return dataSource;
}
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException(e);
}
}
}
使用时:TestC3P0.java
package cn.itcast.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import javax.sql.DataSource;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import cn.itcast.demo.C3P0Utils;
import cn.itcast.demo.JDBCUtils_V3;
public class TestC3P0 {
/**
* 添加用户
*/
@Test
public void testAddUser1(){
Connection conn = null;
//import java.sql.PreparedStatement;
PreparedStatement pstmt = null;
try {
//2.从池子中获取连接
//工具类来获取连接
conn = C3P0Utils.getConnection();
String sql = "insert into newuser values(null,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,"吕布");
pstmt.setString(2,"貂蝉");
int rows = pstmt.executeUpdate();
if(rows > 0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
//3.归还给连接池
//dataSource.backConnection(conn);
JDBCUtils_V3.release(conn, pstmt, null);
}
}
/**
* 添加用户
*/
@Test
public void testAddUser(){
Connection conn = null;
//import java.sql.PreparedStatement;
PreparedStatement pstmt = null;
ComboPooledDataSource dataSource = new ComboPooledDataSource();//加载默认配置
//DataSource dataSource = new ComboPooledDataSource("itheima");//加载有名称的配置
try {
//2.从池子中获取连接
conn = dataSource.getConnection();
String sql = "insert into newuser values(null,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,"王3二");
pstmt.setString(2,"234");
int rows = pstmt.executeUpdate();
if(rows > 0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
//3.归还给连接池
//dataSource.backConnection(conn);
JDBCUtils_V3.release(conn, pstmt, null);
}
}
}
DBCP连接池
导入架包
DBCP不能使用xml进行文件的配置,只能使用配置文件 .properties文件
常见配置项
db.properties配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/web08?useUnicode=true&characterEncoing=utf8
username=root
password=123
使用的时候
这里的话是封装成了工具类方便使用
package cn.itcast.demo;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class DBCPUtils {
private static DataSource dataSource;
static{
try {
//1.加载properties文件
InputStream is = DBCPUtils.class.getClassLoader().getResourceAsStream("db.properties");
//2.加载输入流
Properties props = new Properties();
props.load(is);
//3.使用工具类创建连接池(数据源)
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 获得数据源(连接池)
* @return
*/
public static DataSource getDataSource(){
return dataSource;
}
/**
* 获取连接对象
* @return
*/
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
使用
package cn.itcast.demo;
import java.sql.Connection;
import java.sql.PreparedStatement;
import org.junit.Test;
public class TestDBCP {
@Test
public void testUpdateUserById(){
Connection conn = null;
PreparedStatement pstmt = null;
try {
//1.注册驱动-用DBCP获取连接对象
conn = DBCPUtils.getConnection();
//2.书写一个sql语句
String sql = "update newuser set upassword=? where uid=?";
//3.创建预处理对象
pstmt = conn.prepareStatement(sql);
//4.设置参数给占位符
pstmt.setString(1, "999");
pstmt.setInt(2, 9);
//5.执行更新操作
int rows = pstmt.executeUpdate();
if(rows > 0){
System.out.println("更新成功");
}else{
System.out.println("更新失败");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
第二章 使用DBUtils增删改查的操作
如果只是用JDBC进行开发,冗余代码过多,为了简化JDBC开发,采用apache commons组件一个成员:DBUtils。
DBUtils就是JDBC的简化开发工具包。需要使用技术:连接池(获得连接),SQL语句。
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。
1.JavaBean
package cn.itcast.domain;
//JavaBean组件
//在开发中常用封装数据
public class User {
private int uid;
private String uname;
private String upassword;
public User() {
super();
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUpassword() {
return upassword;
}
public void setUpassword(String upassword) {
this.upassword = upassword;
}
}
2.DBUtils概述
DBUtils是java编程中的数据库操作使用工具,小巧简单使用。
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
DBUtils三个核心功能介绍:
QueryRunner中提供对sql语句操作的API
ResuleSetHandler结构,用于定义select操作后,怎样封装结果集
DbUtils类,它就是一个工具类,定义了关闭资源与实务处理的方法
3.QueryRunner核心类
4.ResuleSetHandler结果集处理类
5.DbUtils工具类
closeQuiety(Connection conn) 关闭连接,如果有异常try后不抛
commitAndCliseQuietly(Connection conn) 提交并关闭连接
rollbackAndCloseQuietly(Connection conn) 回滚并关闭连接
6.DBUtils实现增删改操作
package cn.itcast.demo;
import java.sql.Connection;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Utils {
private static ComboPooledDataSource dataSource = new ComboPooledDataSource("itheima");
public static DataSource getDataSource(){
return dataSource;
}
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (Exception e) {
// TODO: handle exception
throw new RuntimeException(e);
}
}
}
package cn.itcast.test;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import cn.itcast.demo.C3P0Utils;
public class TestDBUtils {
/**
* DBUtils添加操作
*/
@Test
public void testAddUser(){
try {
//1.创建核心类QueryRunner
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//2.编写sql语句
String sql = "insert into newuser values(null,?,?)";
//3.为占位符设置值
Object[] params = {"柳岩","520"};
//4.执行添加操作
int rows = qr.update(sql, params);
if(rows > 0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
} catch (Exception e) {
System.out.println(e);
}
}
/**
* DBUtils修改操作
*/
@Test
public void testUpdateUser(){
try {
//1.创建核心类QueryRunner
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//2.编写sql语句
String sql = "update newuser set upassword=? where uid=?";
//3.为占位符设置值
Object[] params = {"111",4};
//4.执行添加操作
int rows = qr.update(sql, params);
if(rows > 0){
System.out.println("修改成功");
}else{
System.out.println("修改失败");
}
} catch (Exception e) {
System.out.println(e);
}
}
/**
* DBUtils删除操作
*/
@Test
public void testDeleteUser(){
try {
//1.创建核心类QueryRunner
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//2.编写sql语句
String sql = "delete from newuser where uid=?";
//3.为占位符设置值
Object[] params = {4};
//4.执行添加操作
int rows = qr.update(sql, params);
if(rows > 0){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
DBUtils添加操作
DBUtils修改操作
DBUtils删除操作
DBUtils查询操作
ResultSetHandler
我们知道在执行select语句之后得到的是ResultSet,然后我们还需要对ResultSet进行转换,得到最终我们想要的数据。你可以希望把ResultSet的数据放到一个List中,也可能想把数据放到一个Map中,或是一个Bean中。
DBUtils提供了一个接口ResultSetHandler,它就是用来ResultSet转换成目标类型的工具。你可以自己去实现这个接口,把ResultSet转换成你想要的类型。
DBUtils提供了很多个ResultSetHandler接口的实现,这些实现已经基本够用了,我们通常不用自己去实现ResultSet接口了。
MapHandler:单行处理器!把结果集转换成Map<String,Object>,其中列名为键!
MapListHandler:多行处理器!把结果集转换成List<Map<String,Object>>;
BeanHandler:单行处理器!把结果集转换成Bean,该处理器需要Class参数,即Bean的类型;
BeanListHandler:多行处理器!把结果集转换成List;
ColumnListHandler:多行单列处理器!把结果集转换成List,使用ColumnListHandler时需要指定某一列的名称或编号,例如:new ColumListHandler(“name”)表示把name列的数据放到List中。
ScalarHandler:单行单列处理器!把结果集转换成Object。一般用于聚集查询,例如select count(*) from tab_student。
Map处理器
Bean处理器
Column处理器
Scalar处理器
package cn.itcast.test;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.QueryRunner;
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.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;
import cn.itcast.demo.C3P0Utils;
import cn.itcast.domain.User;
public class TestDBUtils2 {
/**
* DBUtils查询操作
* 查询所有用户方法
*/
@Test
public void testQueryAll(){
try {
//1.创建核心类QueryRunner
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//2.编写sql语句
String sql = "select * from newuser";
//3.执行查询操作
List<User> users = qr.query(sql, new BeanListHandler<User>(User.class));
//4.对结果集集合进行遍历
for(User user : users){
System.out.println(user.getUname() + " : " + user.getUpassword());
}
} catch (Exception e) {
System.out.println(e);
}
}
/**
* DBUtils查询操作
* 查询所有用户方法
*/
@Test
public void testQueryAll1(){
try {
//1.创建核心类QueryRunner
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//2.编写sql语句
String sql = "select * from newuser";
//3.执行查询操作
//将结果集中每一条记录封装到Map<String, Object>
//key就是字段名称,value是字段值,在将这些Map封装到List集合中
List<Map<String, Object>> users = qr.query(sql, new MapListHandler());
//4.对结果集集合进行遍历
for(Map<String, Object> user : users){
System.out.println(user);
}
} catch (Exception e) {
System.out.println(e);
}
}
/**
* DBUtils查询操作
* 查询所有用户方法
*/
@Test
public void testQueryAll2(){
try {
//1.创建核心类QueryRunner
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//2.编写sql语句
String sql = "select * from newuser";
//3.执行查询操作
//ColumnListHandler将结果集中指定的列的字段值,封装到一个List集合中
List<Object> list = qr.query(sql, new ColumnListHandler("uname"));
//4.对结果集集合进行遍历
for(Object object : list){
System.out.println(object);
}
} catch (Exception e) {
System.out.println(e);
}
}
/**
* DBUtils查询操作
* 根据id查询用户方法
*/
@Test
public void testQueryById(){
try {
//1.创建核心类QueryRunner
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//2.编写sql语句
String sql = "select * from newuser where uid=?";
//3.为占位符设置值
Object[] params = {7};
//4.执行查询操作
//查询单记录用BeanHandler
User user = qr.query(sql, new BeanHandler<User>(User.class),params);
//5.显示结果集
System.out.println(user.getUname() + " : " + user.getUpassword());
} catch (Exception e) {
System.out.println(e);
}
}
/**
* DBUtils查询操作
* 查询所有用户总个数
*/
@Test
public void testQueryCount(){
try {
//1.创建核心类QueryRunner
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//2.编写sql语句
String sql = "select count(*) from newuser";
//3.执行查询操作
//ScalarHandler用于单数据
long count = (long) qr.query(sql, new ScalarHandler());
System.out.println(count);
} catch (Exception e) {
System.out.println(e);
}
}
}