DBCP、C3P0、DBUtils的jar包和配置文件(百度云盘):点我下载

JDBC

JDBC(Java 数据库连接,Java Database Connectify)是标准的Java访问数据库的API。JDBC定义了数据库的连接,SQL语句的执行以及处理数据库返回的结果等。

Java应用程序使用JDBC API与数据库连接而实际的动作则是由JDBC驱动程序管理器(JDBC Driver Manager)通过JDBC驱动程序(JDBC Driver)与数据库系统进行连接。所以其实真正提供存取数据库功能的是JDBC驱动程序(JDBC Driver)。JDBC驱动程序(JDBC Driver)由数据库厂家自己提供,JDBC提供了一个通用的JDBC Driver Manager,用来管理各种数据库厂家提供的JDBC驱动程序,从而访问其数据库。

JDBC接口层把各个厂家的JDBC驱动程序都进行了包装,这样你在实际开发中只需要使用JDBC API提供给你的接口就够了,而不需要关心底层的细节。

JDBC的使用

  1. JDBC的连接

    JDBC连接数据库,首先需要加载JDBC驱动程序,然后再通过JDBC Driver Manager得到一个对该数据库连接的Connection对象。

    先新建一个名为jdbc.properties配置文件,里面写上用于连接的driverClass,user,password,url四个属性,这样可以避免信息直接暴露在代码里,而且易于维护。

    jdbc.properties:

    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    name=root
    password=123456

    编写一个工具类JDBCUtil,用于得到Connection对象和关闭资源等功能,待会我们将会使用该工具类。

    JDBCUtil:

    package utils;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.sql.*;
    import java.util.Properties; public class JDBCUtil {
    private static String DRIVERCLASS = null;
    private static String NAME = null;
    private static String PASSWORD = null;
    private static String URL = null; //得到配置信息
    static {
    try {
    Properties properties = new Properties();
    InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
    properties.load(is);
    DRIVERCLASS = properties.getProperty("driverClass");
    URL = properties.getProperty("url");
    NAME = properties.getProperty("name");
    PASSWORD = properties.getProperty("password");
    } catch (IOException e) {
    e.printStackTrace();
    }
    } //保证驱动程序只加载一次
    static {
    try {
    Class.forName(DRIVERCLASS);
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    } //得到Connection对象
    public static Connection getConn() {
    try {
    return DriverManager.getConnection(URL, NAME, PASSWORD);
    } catch (SQLException e) {
    e.printStackTrace();
    }
    return null;
    } //关闭操作
    public static void release(Connection conn , Statement st , ResultSet rs) throws SQLException {
    closeResultSet(rs);
    closeStatement(st);
    closeConn(conn);
    } private static void closeConn(Connection conn) throws SQLException {
    if(conn!=null){
    conn.close();
    }
    } private static void closeStatement(Statement st) throws SQLException{
    if(st!=null){
    st.close();
    }
    } private static void closeResultSet(ResultSet rs) throws SQLException{
    if(rs!=null){
    rs.close();
    }
    } }
  2. 执行SQL语句的Statement对象

    Statement对象用于将SQL语句发送到数据库中,主要有三种Statement对象:

    • Statement:用于执行不带参数的简单SQL语句:

      String sql = "select * from stuifo where id= 1";

      Statement st = conn.createStatement();

      st.excuteUpdate(sql);  //执行增删改语句

      st.excuteQuery(sql);  //执行查询语句

      Statement的sql语句必须是完整的,不能带有参数。

    • PreparedStatement(从Statement继承):用于执行带或不带输入参数的预编译SQL语句,用?表示参数,由于PreparedStatement对象已预编译过,所以其执行速度要快于Statement对象。

      String sql = "select * from stuifo where id = ?";

      PreparedStatement ps=conn.prepareStatement(sql);

      ps.setInt(index, value);

      ps.excuteUpdate();  //执行增删改语句

      ps.excuteQuery();  //执行查询语句

    • CallableStatement(从PreparedStatement继承):用于执行数据库存储过程的调用。现在还没用到,用到再学习一下。

    总结:平常开发中使用的最多的是PreparedStatement,因为它可以设置参数,预编译,执行速度更快。

  3. 获得结果集对象

    int num = ps.excuteUpdate();  //执行增删改的语句,返回表中受影响的行数。

    ResultSet rs = ps.excuteQuery();  //执行查询语句,返回查询的结果集,里面存放的是一行一行的数据表的信息。

  4. 处理结果集

    while (resultSet.next()) {
    resultSet.getString(index);  //index代表第几列,从1开始
    resultSet.getString(String);  //使用字段名称
    }

    从数据库中得到字段,数据库中的字段有自己的类型,需要了解数据库中字段类型与Java数据类型的类型转换,这样才能在Java程序中正确的操作数据库中的数据。

    SQL类型 Jdbc(rs)对应方法 返回类型
    BIT(1) bit(10) getBoolean getBytes() Boolean byte[]
    TINYINT getByte() Byte
    SMALLINT getShort() Short
    Int getInt() Int
    BIGINT getLong() Long
    CHAR,VARCHAR,LONGVARCHAR getString() String
    Text(clob) Blob getClob getBlob() Clob Blob
    DATE getDate(), getString() java.sql.Date
    TIME getTime() java.sql.Time
    TIMESTAMP getTimestamp java.sql.Timestamp

数据库连接池

理解数据库连接池

数据库的连接对象创建工作是非常消耗性能的,每次使用时都要重新创建一个Connection对象,这样会导致程序的效率非常低,所以就有了数据库连接池的概念。一开始在内存中开辟一块空间(集合),在池子里放置多个连接对象,我们需要使用连接对象的时候就不需要自己创建连接对象了,直接在里面拿就可以,使用完再归还到池子里,这样能大大的提高程序的效率。

自定义数据库连接池

JDBC提供了统一的数据库连接池接口DataSource,里面定义了很多方法,我们只需要实现该接口即可。我们自定义数据库连接池的功能主要有4个:

  • 一开始先往池子里放入10个连接对象。
  • 一个对外提供连接对象的接口。
  • 回收连接对象的接口。
  • 连接对象用完时,可以扩容。

但是DataSource接口里并没有提供回收连接对象的方法,所以需要我们自己定义一个回收连接对象的方法addBack()。

池子实际上就是一个存有Connection对象的集合,我们对数据库连接池的操作实际就是针对该集合的操作。

必须使用单例模式,所有的程序应该使用同一个数据库连接池对象,否则每次想获取连接时都会创建一个新的数据库连接池对象,这样就完全违背了数据库连接池本来的意义。

MyDataSource:

package utils;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger; /**
* 一个数据库连接池
* 1、一开始先往池子里放10个连接
* 2、通过getConnection获取连接
* 3、用完后addBack归还连接
* 4、扩容
*/
public class MyDataSource implements DataSource { private static final MyDataSource myDataSource = new MyDataSource();
private static final List<Connection> list = new ArrayList<>(); private MyDataSource() {} //一开始放置10个连接
public static MyDataSource getMyDataSource() {
for(int i = 0; i < 10; i++) {
Connection conn = JDBCUtil.getConn();
list.add(conn);
}
return myDataSource;
} //对外提供连接的方法
@Override
public Connection getConnection() throws SQLException {
//扩容,看池子里还有没有连接对象,没有就增加5个
if(list.size() == 0) {
for(int i = 0; i < 5; i++) {
Connection conn = JDBCUtil.getConn();
list.add(conn);
}
}
return list.remove(0);
} //DataSource接口中没有该方法,自己定义的方法,归还Connection
public void addBack(Connection conn) throws SQLException {
list.add(conn);
} @Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
} @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;
}
}

使用自定义数据库连接池MyDataSourceTest:

import utils.JDBCUtil;
import utils.MyDataSource; import java.sql.*; public class MyDataSourceTest {
public static void main (String[] args) {
try {
//得到自定义数据连接池
MyDataSource myDataSource = MyDataSource.getMyDataSource();
//得到连接对象
Connection connection = myDataSource.getConnection();
String sql = "select * from stuifo";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
String string1 = resultSet.getString(1);
String string2 = resultSet.getString(2);
System.out.println(string1 + string2);
}
//归还连接对象
myDataSource.addBack(connection);
//释放资源
JDBCUtil.release(connection, statement, resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
}
}

这个自定义数据库连接池实现了基本的功能,但是有一个很大的问题,在上面提到JDBC提供的DataSource接口没有addBack()方法,这个方法是我们在实现DataSource接口时自己定义的,我们额外的给他添加了该功能,这意味着什么呢?

  • 无法使用面向接口编程:

    DataSource dataSource = MyDataSource().getMyDataSource();

    dataSource.addBack(connection);  ✖这是错的,DataSource接口中并没有定义该方法

  • 用户在使用该MyDataSource时,必须记住还有一个额外方法addBack(),这个方法不是JDBC规范的方法

    MyDataSource myDataSource = MyDataSource().getMyDataSource();

    myDataSource.addBack(connection);

如何解决自定义数据库连接池出现的问题呢?

可以考虑不在MyDataSource中实现归还连接对象的功能,这样就可以实现面向接口编程,我们可以修改Connection接口中的那个close方法。 原来的Connection对象的close方法,是真的关闭连接。 打算修改这个close方法,以后在调用close, 并不是真的关闭,而是归还连接对象。

如何扩展一个方法呢?

  • 直接修改源代码:这是不切实际的  ✖
  • 继承:但是不知道父类是谁,Connection只是一个接口  ✖
  • 装饰者模式:装饰者模式指的是在不改变原类和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。  ✔

如何理解装饰者模式?详细了解请看设计模式中装饰者模式这一篇,go There。

这里简单来说就是创建一个包装对象,用来包装连接对象,包装对象继承Connection接口,连接对象以Connection接口传到包装对象中,包装对象再扩充连接对象。

ConnectionWrap:

package utils;

import java.sql.*;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor; public class ConnectionWrap implements Connection { private Connection connection = null;
private List<Connection> list = null; public ConnectionWrap(Connection connection, List<Connection> list) {
super();
this.connection = connection;
this.list = list;
} @Override
public void close() throws SQLException {
System.out.println("有人归还了");
list.add(connection);
} @Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return connection.prepareStatement(sql);
} @Override
public Statement createStatement() throws SQLException {
return connection.createStatement();
} @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;
} @Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
} @Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}

改写后的MyDataSource:

package utils;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger; public class MyDataSource implements DataSource { private static final MyDataSource myDataSource = new MyDataSource();
private static final List<Connection> list = new ArrayList<>(); private MyDataSource() {} //一开始放置10个连接
public static MyDataSource getMyDataSource() {
for(int i = 0; i < 10; i++) {
Connection conn = JDBCUtil.getConn();
list.add(conn);
}
return myDataSource;
} //对外提供连接的方法
@Override
public Connection getConnection() throws SQLException {
//扩容,看池子里还有没有连接对象,没有就增加5个
if(list.size() == 0) {
for(int i = 0; i < 5; i++) {
Connection conn = JDBCUtil.getConn();
list.add(conn);
}
}
Connection conn = list.remove(0);
return new ConnectionWrap(conn, list);
} @Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
} @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;
}
}

改写后的MyDataSourceTest:

import utils.JDBCUtil;
import utils.MyDataSource; import javax.sql.DataSource;
import java.sql.*; public class MyDataSourceTest {
public static void main (String[] args) {
try {
//得到自定义数据连接池
DataSource dataSource = MyDataSource.getMyDataSource();
//得到连接对象
Connection connection = dataSource.getConnection();
String sql = "select * from stuifo";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
String string1 = resultSet.getString(1);
String string2 = resultSet.getString(2);
System.out.println(string1 + string2);
}
//释放资源
JDBCUtil.release(connection, statement, resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
}
}

使用开源连接池

DBCP

DBCP(DataBase Connection Pool)数据库连接池,是java数据库连接池的一种,由Apache开发,通过数据库连接池,可以让程序自动管理数据库连接的释放和断开。

使用之前需要导入两个jar包,commons-dbcp.jar和commons-pool.jar。

使用:

首先要编写配置文件dbcpconfig.properties,这个配置文件定义了连接设置,即数据库连接的四个参数,还有dbcp连接池的一些基本配置,比如初始化连接对象个数,最大连接数量等等。。。

dbcpconfig.properties:

#连接设置
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student
name=root
password=123456 #<!-- 初始化连接 -->
initialSize=10 #最大连接数量
maxActive=50 #<!-- 最大空闲连接 -->
maxIdle=20 #<!-- 最小空闲连接 -->
minIdle=5 #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk #指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

使用dbcp连接池做一个简单的查询DBCPTest:

package utils;

import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties; public class DBCPTest {
private static void main(String[] args) throws Exception {
//得到配置文件
Properties properties = new Properties();
InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
properties.load(is);
//创建数据库连接池
BasicDataSourceFactory factory = new BasicDataSourceFactory();
DataSource dataSource = factory.createDataSource(properties);
//简单查询
Connection conn = dataSource.getConnection();
String sql = "select * from stuifo";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
ResultSet rs = preparedStatement.executeQuery();
while(rs.next()) {
String value1 = rs.getString(1);
String value2 = rs.getString(2);
System.out.println(value1 + " " + value2);
}
conn.close();
preparedStatement.close();
rs.close();
}
}

C3P0

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。

使用时需要添加C3P0的两个jar包,c3p0.jar和mchange-commons-java.jar。

使用:

首先也是要编写配置文件c3p0-config.xml,里面的内容与上面dbcp的配置文件dbcpconfig.properties内容大体一致,也是一些初始化的参数。

c3p0-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config> <!-- default-config 默认的配置, -->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost/student?useSSL=false</property>
<property name="user">root</property>
<property name="password">123456</property> <property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config> <!-- This app is massive! -->
<named-config name="oracle">
<property name="acquireIncrement">50</property>
<property name="initialPoolSize">100</property>
<property name="minPoolSize">50</property>
<property name="maxPoolSize">1000</property> <!-- intergalactoApp adopts a different approach to configuring statement caching -->
<property name="maxStatements">0</property>
<property name="maxStatementsPerConnection">5</property> <!-- he's important, but there's only one of him -->
<user-overrides user="master-of-the-universe">
<property name="acquireIncrement">1</property>
<property name="initialPoolSize">1</property>
<property name="minPoolSize">1</property>
<property name="maxPoolSize">5</property>
<property name="maxStatementsPerConnection">50</property>
</user-overrides>
</named-config> </c3p0-config>

把该c3p0连接池封装在JDBCUtil中,从连接池中得到连接对象,就不需要我们自己编写加载JDBC驱动器,获取连接对象等等。

优化后的JDBCUtil:

package utils;

import java.sql.*;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource; public class JDBCUtil { private static ComboPooledDataSource dataSource = null;
static{
dataSource = new ComboPooledDataSource();
} public static DataSource getDataSource() {
return dataSource;
} public static Connection getConn() throws SQLException{
return dataSource.getConnection();
} //关闭操作
public static void release(Connection conn , Statement st , ResultSet rs) {
closeResultSet(rs);
closeStatement(st);
closeConn(conn);
} private static void closeConn(Connection conn) {
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} private static void closeStatement(Statement st) {
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} private static void closeResultSet(ResultSet rs) {
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} }

DBUtils

Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。

使用时需要添加dbutil的jar包,commons-dbutils.jar。

使用:

首先需要创建QueryRunner对象,这里就需要使用到上面基于C3P0连接池的JDBCUtil,创建QueryRunner对象需要向其构造函数传入一个数据库连接池。

QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());

现在就可以使用该queryRunner对象进行CRUD操作了。

以数据库student下的stuifo表为例:

  1. 查询

    查询:queryRunner.query(sql, hander, params),sql为sql语句,hander为java.sql.ResultSetHander接口的实现类,该接口用于处理java.sql.ResultSet,将查询到的数据按要求转换为另一种形式,比如自定义对象,ArrayList,Map...,params为sql语句中的参数(可变参数,取决于?的个数)。

    ResultSetHandler接口的实现类:

    • ArrayHandler :将ResultSet中第一行的数据转化成对象数组
    • ArrayListHandler将ResultSet中所有的数据转化成List,List中存放的是Object[]
    • BeanHandler :将ResultSet中第一行的数据转化成类对象
    • BeanListHandler :将ResultSet中所有的数据转化成List,List中存放的是类对象
    • ColumnListHandler :将ResultSet中某一列的数据存成List,List中存放的是Object对象
    • KeyedHandler :将ResultSet中存成映射,key为某一列对应为Map。Map中存放的是数据
    • MapHandler :将ResultSet中第一行的数据存成Map映射
    • MapListHandler :将ResultSet中所有的数据存成List。List中存放的是Map
    • ScalarHandler :将ResultSet中一条记录的其中某一列的数据存成Object,常用于聚合函数。

    举例:

    创建一个Student类,里面定义了上面id、scold、name、sex四个属性,Student类中的属性必须要与数据库中的字段名一一对应,否则将会查询失败。

    Student:

    package model;
    
    public class Student {
    private int id;
    private String scold;
    private String name;
    private String sex; public Student(int id, String scold, String name, String sex) {
    this.id = id;
    this.scold = scold;
    this.name = name;
    this.sex = sex;
    } public Student() {
    } public int getId() {
    return id;
    } public void setId(int id) {
    this.id = id;
    } public String getScold() {
    return scold;
    } public void setScold(String scold) {
    this.scold = scold;
    } public String getName() {
    return name;
    } public void setName(String name) {
    this.name = name;
    } public String getSex() {
    return sex;
    } public void setSex(String sex) {
    this.sex = sex;
    } @Override
    public String toString() {
    return "Student{" +
    "id=" + id +
    ", scold='" + scold + '\'' +
    ", name='" + name + '\'' +
    ", sex='" + sex + '\'' +
    '}';
    }
    }

    BeanHander:

    private static void main(String[] args) throws Exception {
    //查询id为1的学生
    QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
    String sql = "select * from stuifo where id = ?";
    int id = 1;
    Student student = queryRunner.query(sql, new BeanHandler<>(Student.class), id);
    System.out.println(student.toString());
    }

    BeanListHander:

    public static void main(String[] args) throws Exception {
    //查询所有学生
    QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
    String sql = "select * from stuifo";
    List<Student> list = queryRunner.query(sql, new BeanListHandler<>(Student.class));
    System.out.println(list);
    }

    ScalarHandler:

    public static void main(String[] args) throws Exception {
    //查询一共有多少学生
    QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
    String sql = "select count(*) from stuifo";
    Object obj = queryRunner.query(sql, new ScalarHandler<>());
    Long num = (Long) obj;
    System.out.println(num.intValue());
    }
  2. 增删改

    增删改:queryRunner.update(sql, params),第一个参数sql为要执行的sql语句,后面为sql语句中的参数(可变参数,取决于sql语句中?号的多少)。

    插入学生:

    public static void main(String[] args) throws Exception {
    //插入学生
    QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
    String sql = "insert into stuifo values(null, ?, ?, ?)";
    String scold = "111111";
    String name = "大耳朵图图";
    String sex = "男";
    queryRunner.update(sql, scold, name, sex);
    }  

    更新学生信息:

    public static void main(String[] args) throws Exception {
    //修改id为1的学生的性别为女
    QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
    String sql = "update stuifo set sex = ? where id = ?";
    int id = 1;
    String sex = "女";
    queryRunner.update(sql, sex, id);
    }

    删除学生:

    public static void main(String[] args) throws Exception {
    //删除id为1的学生
    QueryRunner queryRunner = new QueryRunner(JDBCUtil.getDataSource());
    String sql = "delete from stuifo where id = ?";
    int id = 1;
    queryRunner.update(sql, id);
    }

总结:虽然这一篇内容很多,但是实际上就是对数据库的一些操作,平常开发中只要使用基于C3P0连接池的JDBCUtil工具类,和DBUtils工具类就可以完成基本开发了。这样比我们自己手写创建连接,进行CRUD操作,高效多了。

Java Web(九) JDBC及数据库连接池及DBCP,c3p0,dbutils的使用的更多相关文章

  1. Java Web(十) JDBC的增删改查,C3P0等连接池,dbutils框架的使用

    前面做了一个非常垃圾的小demo,真的无法直面它,菜的抠脚啊,真的菜,好好努力把.菜鸡. --WH 一.JDBC是什么? Java Data Base Connectivity,java数据库连接,在 ...

  2. 数据库连接JDBC和数据库连接池C3P0自定义的java封装类

    数据库连接JDBC和数据库连接池C3P0自定义的java封装类 使用以下的包装类都需要自己有JDBC的驱动jar包: 如 mysql-connector-java-5.1.26-bin.jar(5.1 ...

  3. Java -- JDBC 学习--数据库连接池

    JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤: 在主程序(如servlet.beans)中建立数据库连接. 进行sql操作 断开数据库连接. 这种模式开 ...

  4. Java数据库连接池比较(c3p0,dbcp,proxool和BoneCP)

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp21 Java框架数据库连接池比较(c3p0,dbcp和proxool,Bo ...

  5. 第77节:Java中的事务和数据库连接池和DBUtiles

    第77节:Java中的事务和数据库连接池和DBUtiles 前言 看哭你,字数:8803,承蒙关照,谢谢朋友点赞! 事务 Transaction事务,什么是事务,事务是包含一组操作,这组操作里面包含许 ...

  6. Java操作数据库——手动实现数据库连接池

    Java操作数据库——手动实现数据库连接池 摘要:本文主要学习了如何手动实现一个数据库连接池,以及在这基础上的一些改进. 部分内容来自以下博客: https://blog.csdn.net/soonf ...

  7. 开源数据库连接池之DBCP

    本篇介绍几种开源数据库连接池,同时重点讲述如何使用Apache公司的的DBCP数据库连接池. 前面一篇博客已经重点讲述了使用数据库连接池的好处,即是将多次创建连接转变为一次创建而使用长连接模式.这样能 ...

  8. 数据库连接池 - (druid、c3p0、dbcp)

    概述: 在这里所谓的数据库连接是指通过网络协议与数据库服务之间建立的TCP连接.通常,与数据库服务进行通信的网络协议无需由应用程序本身实现. 原因有三: 实现复杂度大,需要充分理解和掌握相应的通信协议 ...

  9. JDBC 学习笔记(三)—— 数据源(数据库连接池):DBCP数据源、C3P0 数据源以及自定义数据源技术

    本文目录:        1.应用程序直接获取连接的缺点(图解)        2.使用数据库连接池优化程序性能(图解)        3.可扩展增强某个类方法的功能的三种方式        4.自定 ...

随机推荐

  1. Windows下pipenv将虚环境文件的位置设置在项目根目录下

    在windows下使用pipenv shell时,虚拟环境文件夹会在C:\Users\Administrator\.virtualenvs\目录下默认创建,为了方便管理,将这个虚环境的文件的位置更改一 ...

  2. 虹软 Android 人脸检测与人脸识别集成分享

    目前我们的应用内使用了 ArcFace 的人脸检测功能,其他的我们并不了解,所以这里就和大家分享一下我们的集成过程和一些使用心得 集成ArcFace FD 的集成过程非常简单 在 ArcFace FD ...

  3. 全排列问题Ⅱ(Java实现)

    题目: 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2], [1,2,1], [2,1,1] ]这个问题和我的上一篇问题分析的手法一样 ...

  4. Appium解决搜索框问题

    appium解决搜索框: 1. 点击搜索,手工测试会弹出键盘,需要点击键盘上的搜索按钮. 2.但自动化的时候,键盘不能弹出.所以我们可以用回车等keycode代替搜索按钮. Press Keycode ...

  5. HDOJ 1023 Train Problem II

    考虑第1个火车出站的时刻,从1到n都有可能,如果它是第i个出栈,那么前面有规模为i-1的子问题,后面有规模为n-i的子问题.累加.

  6. android ------- TCP/IP

    TCP/IP 是针对因特网的通信协议. 什么是 TCP/IP? TCP/IP 是供已连接因特网的计算机进行通信的通信协议. TCP/IP 指传输控制协议/网际协议 (Transmission Cont ...

  7. Spring Batch 背景

    在开源项目及其相关社区把大部分注意力集中在基于 web 和 SOA 基于消息机制的框架中时,基于 Java 的批处理框架却无人问津,尽管在企业 T 环境中一直都有这种批处理的需求.但因为缺乏一个标准的 ...

  8. Confluence 6 内容在空间中是如何组织的

    你可以将空间考虑为一个容器,在这个容器中保持了有关你项目中所有重要的东西,包括小组,项目或者项目相关的工作.这些东西有很高的自主性,这表示的是每个空间都有自己的的页面,文件,评论以及 RSS 新闻源. ...

  9. Post四种Content-Type

    application/x-www-form-urlencoded 这应该是最常见的 POST 提交数据的方式了.浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 app ...

  10. 查看cookie的快捷方法

    1.url中输入数字+javascript:alert(document.cookie)   如:2javascript:alert(document.cookie)   ,然后在浏览器中去掉2,回车 ...