javaWeb学习记录:c3p0数据库连接池;DBUtils工具

1. c3p0数据库连接池

让我想起了星球大战里的C-3PO,哈哈。

1.1 数据库连接池的概念

用池来管理Connection,这可以重复使用Connection。有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。池就可以再利用这个Connection对象了。

1.2 c3p0数据库连接池例子

需要的jar包:

  • c3p0-0.9.2-pre1.jar
  • mchange-commons-0.2.jar
  • mysql-connector-java-5.1.37-bin.jar

代码如下:

ComboPooledDataSource ds = new ComboPooledDataSource();
//基本配置
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
ds.setUser("root");
ds.setPassword("dongjiong");
ds.setDriverClass("com.mysql.jdbc.Driver");

//每次的增量
ds.setAcquireIncrement(5);
//初始化连接数
ds.setInitialPoolSize(30);
//最少连接数
ds.setMinPoolSize(2);
//最多连接数
ds.setMaxPoolSize(50);

//得到连接器
Connection con = ds.getConnection();
System.out.println(con);
//归还给池
con.close();

c3p0也可以指定配置文件,而且配置文件可以是properties,也可以是xml的。当然xml的高级一些了。但是c3p0的配置文件名必须为c3p0-config.xml,并且必须放在类路径下。
配置文件要求:

  • 文件名称:必须叫c3p0-config.xml
  • 文件位置:必须在src下


    c3p0-config.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 这是默认配置信息 -->
    <default-config> 
        <!-- 连接四大参数配置 -->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">dongjiong</property>
        <!-- 池参数配置 -->
        <property name="acquireIncrement">3</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">2</property>
        <property name="maxPoolSize">10</property>
    </default-config>
</c3p0-config>

xml文件配置好之后,代码里就不用再配置了,直接像下面的代码那样调用就行:

ComboPooledDataSource ds = new ComboPooledDataSource();
//得到连接器
Connection con = ds.getConnection();
System.out.println(con);
//归还给池
con.close();

c3p0的配置文件中可以配置多个连接信息,可以给每个配置起个名字,这样可以方便的通过配置名称来切换配置信息。上面xml文件中默认配置为mysql的配置,也可以给oracle数据库配置一下连接信息,起名为oracle-config,使用时把名字作为参数传给程序。
xml文件内加入下面的信息:

<!-- 专门为oracle提供的配置信息 -->
<named-config name="oracle-config"> 
    <property>...</property>
    ...
    <property>...</property>
</named-config>

代码里使用时:

ComboPooledDataSource ds = new ComboPooledDataSource("oracle-config");
//得到连接器
Connection con = ds.getConnection();
System.out.println(con);
//归还给池
con.close();

2. jdbcUtils类

之前每次用JDBC时都要写那些基本配置的代码,所以就把这些代码写到了jdbcUtils类里的一个静态方法里,返回一个Connection,然后直接在其他类里调用这个方法就可以了,减少了重复代码的书写,提高效率。这个类的代码如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class jdbcUtils {
    private static String url =  "jdbc:mysql://localhost:3306/test";        
    private static String username = "root";
    private static String password = "dongjiong";

    static {
        try{
            Class.forName("com.mysql.jdbc.Driver");
        }catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() throws SQLException{
        return DriverManager.getConnection(url, username, password);
    }
}

现在使用了c3p0数据库连接池,这个类里的代码需要改一下:

import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;

public class jdbcUtils {
    // 配置文件的默认配置!要求你必须给出c3p0-config.xml!!!
    private static ComboPooledDataSource dataSource = new ComboPooledDataSource();

    /**
     * 使用连接池返回一个连接对象
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException{
        return dataSource.getConnection();
    }

    /**
     * 返回连接池对象!
     * @return
     */
    public static DataSource getDataSource() {
        return dataSource;
    }
}

3. DBUtils

Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。其最核心的特性是结果集的封装,可以直接将查询出来的结果集封装成JavaBean,这就为我们做了最枯燥乏味、最容易出错的一大部分工作。

使用DBUtils需要注意的一些问题:

  1. DBUtils对结果集自动封装为JavaBean是有着苛刻要求的:必须满足JavaBean的规范,其次Bean的getter与setter方法的名字与结果集的列名(数据库表的列名)一一对应,而不要求JavaBean的私有成员与表结果集列名一一对应。比如:
    person表中有个字段叫:address,那么对应的JavaBean的Person类中必须有getAddress和setAddress两个方法,而Person类中可以将address属性命名为add,这是没问题的。
  2. 对于JavaBean的成员类型定义,有一条原则那就是:尽可能使用包装类型,而不要使用基本类型。
    //错误
    int a1 = (Integer) null;
    boolean x1 = (Boolean)null;
    //正确
    Integer a2 = (Integer) null;
    Boolean x2 = (Boolean)null;

实际上就是为了保证在查询结果为null的时候,也不会因为给基本类型赋null值而发生错误。

DBUtils主要类:QueryRunner

QueryRunner类下面有几个经常使用的方法:

  • update():执行insert、update、delete操作
  • query():执行select语句
  • batch():执行批处理

假设有一个student表,它有三列:id,name,age。对它进行一些操作。

update():执行insert、update、delete操作

@Test
public void insert() throws Exception{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "INSERT INTO student VALUES(?,?,?)";
    Object[] params = {3,"jinjin",22};
    qr.update(sql, params);
}

@Test
public void update() throws Exception{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "UPDATE student SET name=? WHERE id=?";
    Object[] params = {"yaoyao",3};
    qr.update(sql, params);
}

@Test
public void delete() throws Exception{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "DELETE FROM student WHERE id=?";
    Object[] params = {3};
    qr.update(sql, params);
}

query():执行select语句

@Test
public void select() throws SQLException{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "SELECT * FROM student WHERE id=?";
    Object[] params = {2};

    Student student = qr.query(sql,new BeanHandler<Student>(Student.class),params);
    System.out.println(student);
}

我们知道在执行select语句之后得到的是ResultSet,然后我们还需要对ResultSet进行转换,得到最终我们想要的数据。你可能希望把ResultSet的数据放到一个List中,也可能想把数据放到一个Map中,或是一个Bean中。DBUtils提供了一个接口ResultSetHandler,它就是用来ResultSet转换成目标类型的工具。DBUtils提供了很多个ResultSetHandler接口的实现。
如下:

  1. MapHandler:单行处理器!把结果集转换成Map<String,Object>,其中列名为键!
  2. MapListHandler:多行处理器!把结果集转换成List<Map<String,Object>>;
  3. BeanHandler:单行处理器!把结果集转换成Bean,该处理器需要Class参数,即Bean的类型;
  4. BeanListHandler:多行处理器!把结果集转换成List;
  5. ColumnListHandler:多行单列处理器!把结果集转换成List<Object>,使用ColumnListHandler时需要指定某一列的名称或编号,例如:new ColumListHandler(“name”) 表示把name列的数据放到List中。
  6. ScalarHandler:单行单列处理器!把结果集转换成Object。一般用于聚集查询,例如select count(*) from tab_student。
  7. ArrayHandler:把结果集中的第一行数据转成对象数组。
  8. ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。
  9. KeyedHandler:将结果集中的每一行数据都封装到一个Map里,然后再根据指定的key把每个Map再存放到一个Map里。

举几个例子吧:

MapHandler:
@Test
public void select() throws SQLException{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "SELECT * FROM student WHERE id=?";
    Object[] params = {2};

    Map<String, Object> student = qr.query(sql,new MapHandler(),params);
    System.out.println(student);
}
MapListHandler
@Test
public void select() throws SQLException{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "SELECT * FROM student";

    List<Map<String, Object>> stuList = qr.query(sql,new MapListHandler());
    System.out.println(stuList);
}
BeanHandler
@Test
public void select() throws SQLException{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "SELECT * FROM student WHERE id=?";
    Object[] params = {2};

    Student student = qr.query(sql,new BeanHandler<Student>(Student.class),params);
    System.out.println(student);
}
BeanListHandler
@Test
public void select() throws SQLException{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "SELECT * FROM student";

    List<Student> stuList = qr.query(sql,new BeanListHandler<Student>(Student.class));
    System.out.println(stuList);
}
ScalarHandler
@Test
public void select() throws SQLException{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "SELECT COUNT(*) FROM student";

    Number count = (Number) qr.query(sql,new ScalarHandler());//必须这样写,然后再转换
    int num = count.intValue();

    System.out.println(num);
}

对聚合函数的查询结果,有的驱动返回的是Long,有的返回的是BigInteger,所以这里我们把它转换成Number,Number是Long和BigInteger的父类!然后我们再调用Number的intValue()或longValue()方法转成我们需要的类型。

ColumnListHandler
@Test
public void select() throws SQLException{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "SELECT name FROM student";

    List<Object> names = qr.query(sql, new ColumnListHandler());

    System.out.println(names);
}

batch():执行批处理

我们更新一行记录时需要指定一个Object[]数组为参数,如果是批处理,处理多行数据,那么就要指定一个二维数组:Object[][]为参数。其中每个Object[]对应一行记录。

@Test
public void insertBath() throws SQLException{
    QueryRunner qr = new QueryRunner(jdbcUtils.getDataSource());
    String sql = "INSERT INTO student VALUES(?,?,?)";

    Object[][] params = new Object[10][]; //表示 要插入10行记录
    for(int i = 0; i < params.length; i++) {
        params[i] = new Object[]{30 + i,"name" + i,10+i};
    }

    qr.batch (sql, params);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值