返回顶部

JDBC

jdbc定义

Java提供访问数据库规范称为JDBC(Java Data Base Connectivity,java数据库连接),而生产厂商提供规范的实现类称为驱动。

JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库。每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。

 

JDBC开发步骤

1.    注册驱动
告知JVM使用的是哪一个数据库的驱动

2.    获得连接
使用JDBC中的类,完成对MySQL数据库的连接

3.    获得语句执行平台
通过连接对象获取对SQL语句的执行者对象

4.    执行sql语句
使用执行者对象,向数据库执行SQL语句

5.    处理结果

6.    释放资源
执行一堆close().

 

PreparedStatement 预处理对象

因为SQL注入问题,采用 PreparedStatement 预处理对象来解决。使用PreparedStatement预处理对象时的常用方法:

  • int executeUpdate(); --执行insert update delete语句.
  • ResultSet executeQuery(); --执行select语句.
  • boolean execute(); --执行select返回true 执行其他的语句返回false.
public void demo01() throws Exception {
    // 1注册驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 2获取连接
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
    // 3获得预处理对象
    String sql = "insert into sort(sname) values(?)";
    PreparedStatement stat = conn.prepareStatement(sql);
    // 4 SQL语句占位符设置实际参数
    stat.setString(1, "奢侈品");
    // 5执行SQL语句
    int line = stat.executeUpdate();
    System.out.println("新添加记录数:" + line);
    // 6释放资源
    stat.close();
    conn.close();
}

public void demo02() throws Exception {
    // 1注册驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 2获取连接
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
    // 3获得预处理对象中
    String sql = "update sort set sname=? where sid=?";
    PreparedStatement stat = conn.prepareStatement(sql);
    // 4 SQL语句占位符设置实际参数
    stat.setString(1, "数码产品");
    stat.setInt(2, 1);
    // 5执行SQL语句
    int line = stat.executeUpdate();
    System.out.println("更新记录数:" + line);
    // 6释放资源
    stat.close();
    conn.close();
}

public void demo03() throws Exception {
    // 1注册驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 2获取连接
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
    // 3获得预处理对象
    String sql = "delete from sort where sid=?";
    PreparedStatement stat = conn.prepareStatement(sql);
    // 4 SQL语句占位符设置实际参数
    stat.setInt(1, 1);
    // 5执行SQL语句
    int line = stat.executeUpdate();
    System.out.println("删除记录数:" + line);
    // 6释放资源
    stat.close();
    conn.close();
}

public void demo05() throws Exception {
    // 1注册驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 2获取连接
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
    // 3获得预处理对象
    String sql = "select * from sort where sname=?";
    PreparedStatement stat = conn.prepareStatement(sql);
    // 4 SQL语句占位符设置实际参数
    stat.setString(1, "奢侈品");
    // 5执行SQL语句
    ResultSet rs = stat.executeQuery();
    // 6处理结果集(遍历结果集合)
    while( rs.next() ){
        //获取当前行的分类ID
        String sid = rs.getString("sid");//方法参数为数据库表中的列名
        //获取当前行的分类名称
        String sname = rs.getString("sname");
        //显示数据
        System.out.println(sid+"-----"+sname);
    }
    // 7释放资源
    rs.close();
    stat.close();
    conn.close();
}
PreparedStatement的执行方法

 

自己处理JDBC连接

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
user=root
password=root
db.propertie
public class JDBCUtils {
    private static String driver;
    private static String url;
    private static String user;
    private static String password;
    // 静态代码块
    static {
        try {
            // 1 使用Properties处理流
            // 使用load()方法加载指定的流
            Properties props = new Properties();
            Reader is = new FileReader("db.properties");
            props.load(is);
            // 2 使用getProperty(key),通过key获得需要的值,
            driver = props.getProperty("driver");
            url = props.getProperty("url");
            user = props.getProperty("user");
            password = props.getProperty("password");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获得连接
     */
    public static Connection getConnection() {
        try {
            // 1 注册驱动
            Class.forName(driver);
            // 2 获得连接
            Connection conn = DriverManager.getConnection(url, user, password);
            return conn;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
JDBCUtils
public class Demo {
    @Test
    public void insert(){
        try{
            //1,获取连接对象
            Connection conn = JDBCUtils.getConnection();
            //2,指定要执行的SQL语句
            String sql = "INSERT INTO zhangwu(name,money,parent) VALUES(?,?,?)";
            //4,获取SQL语句的执行对象 PreparedStatement
            PreparedStatement ppstat = conn.prepareStatement(sql);
            //5,执行SQL语句
            ppstat.setString(1, "股票收入");
            ppstat.setDouble(2, 5000);
            ppstat.setString(3, "收入");
            int line = ppstat.executeUpdate();
            //6,处理结果集
            System.out.println("line=" + line);
            //7,关闭连接
            ppstat.close();
            conn.close();
        } catch(SQLException e){
            throw new RuntimeException(e);
        }
    }
}
测试Demo

其中 new FileReader("db.properties"); 在实际中还有可能的方式为 JDBCUtils.class.getClassLoader().getResourceAsStream("db.propeties");

 

Dbutils

自己处理的时候,比较繁琐,可以引入工具jar:apache commons组件成员 commons-dbutils-1.6.jar 是JDBC的简化开发工具包。
DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
Dbutils三个核心功能:
QueryRunner中提供对sql语句操作的API。
ResultSetHandler接口,用于定义select操作后,怎样封装结果集。
DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法。

QueryRunner核心类

QueryRunner增删改操作

update(Connection conn, String sql, Object... params) ,用来完成表数据的增加、删除、更新操作

public void insert(){
    try {
        //获取一个用来执行SQL语句的对象   QueryRunner
        QueryRunner qr = new QueryRunner();
        
        String sql = "INSERT INTO zhangwu(name,money,parent) VALUES(?,?,?)";
        Object[] params = {"股票收入", 5500, "收入"};
        Connection conn = JDBCUtils.getConnection();
        int line = qr.update(conn,sql,params);// 用来完成表数据的增加、删除、更新操作
        //结果集处理
        System.out.println("line = " + line);
        
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

public void update(){
    try {
        //创建一个QueryRunner对象,用来完成SQL语句的执行
        QueryRunner qr = new QueryRunner();
        //执行SQL语句
        String sql = "UPDATE zhangwu SET money = money+1000 WHERE name=?";
        Object[] params = {"股票收入"};
        Connection conn = JDBCUtils.getConnection();
        int line = qr.update(conn, sql, params);
        //结果集的处理
        System.out.println("line="+line);
        
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

public void delete(){
    try {
        //创建一个QueryRunner对象,用来完成SQL语句的执行
        QueryRunner qr = new QueryRunner();
        //执行SQL语句
        String sql = "DELETE FROM zhangwu WHERE name = ?";
        Object[] params = {"股票收入"};
        Connection conn = JDBCUtils.getConnection();
        int line = qr.update(conn, sql, params);
        //结果集的处理
        System.out.println("line="+line);
        
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}
queryRunner增删改

QueryRunner查询操作

query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) ,用来完成表数据的查询操作

ResultSetHandler结果集处理类

ArrayHandler

将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值

ArrayListHandler

将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。

BeanHandler

将结果集中第一条记录封装到一个指定的javaBean中。

BeanListHandler

将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中

ColumnListHandler

将结果集中指定的列的字段值,封装到一个List集合中

ScalarHandler

它是用于单数据。例如select count(*) from 表操作。

MapHandler

将结果集第一行封装到Map集合中,Key 列名, Value 该列数据

MapListHandler

将结果集每一行封装到Map集合中,Key 列名, Value 该列数据,Map集合存储到List集合

public class ArrayHandlerDemo {
    @Test
    public void method(){
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT * FROM zhangwu";
            Object[] params = {};
            Connection conn = JDBCUtils.getConnection();
            Object[] objArray = qr.query(conn, sql, new ArrayHandler(), params);
            //结果集的处理
            System.out.println( Arrays.toString(objArray) );
            
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

public class ArrayListHandlerDemo {
    @Test
    public void method(){
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT * FROM zhangwu WHERE money>?";
            Object[] params = {2000};
            Connection conn = JDBCUtils.getConnection();
             List<Object[]> list = qr.query(conn, sql, new ArrayListHandler(), params);
            //结果集的处理
             for (Object[] objArray : list) {
                System.out.println(  Arrays.toString(objArray) );
            }
            
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

public class BeanHandlerDemo {
    @Test
    public void method(){
        try{
            //获取QueryRunner 
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT * FROM zhangwu WHERE id=?";
            Object[] params = {1};
            Connection conn = JDBCUtils.getConnection();
            ZhangWu zw = qr.query(conn, sql, new BeanHandler<ZhangWu>(ZhangWu.class), params);
            //结果集处理
            System.out.println(zw);
            
            conn.close();
        } catch(SQLException e){
            throw new RuntimeException(e);
        }
    }
}

public class BeanListHandlerDemo {
    @Test
    public void method(){
        try{
            //获取QueryRunner 
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT * FROM zhangwu WHERE money>?";
            Object[] params = {2000};
            Connection conn = JDBCUtils.getConnection();
            List<ZhangWu> list = qr.query(conn, sql, new BeanListHandler<ZhangWu>(ZhangWu.class), params);
            //结果集处理
            for (ZhangWu zw : list) {
                System.out.println(zw);
            }
            
            conn.close();
        } catch(SQLException e){
            throw new RuntimeException(e);
        }
    }
}

public class ColumnListHandlerDemo {
    @Test
    public void method(){
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();
            //执行SQL语句
            String sql = "SELECT name FROM zhangwu WHERE money>?";
            Object[] params = {2000};
            Connection conn = JDBCUtils.getConnection();
            List<String> list = qr.query(conn, sql, new ColumnListHandler<String>(), params); 
            //结果集的处理
            for (String str : list) {
                System.out.println(str);
            }

            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

public class ScalarHandlerDemo {
    @Test
    public void method(){
        try {
            //获取QueryRunner对象
            QueryRunner qr = new QueryRunner();
            
            //执行SQL语句
            String sql = "SELECT MAX(money) FROM zhangwu";
            Object[] params = {};
            Connection conn = JDBCUtils.getConnection();
            Double max = qr.query(conn, sql, new ScalarHandler<Double>(), params);
            //结果集的处理
            System.out.println("max=" + max);
            
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
ResultSetHandler例子

 

连接池

“获得连接”或“释放资源”是非常消耗系统资源的两个过程,为了解决此类性能问题,通常情况我们采用连接池技术,来共享连接Connection。
Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池。
常见的连接池:DBCP、C3P0。

DBCP

也是一个开源的连接池,是Apache Common成员之一,在企业开发中也比较常见,tomcat内置的连接池。
commons-dbcp1.4.jar commons-pool-1.5.6.jar

public class JDBCUtils {
    public static final String DRIVER = "com.mysql.jdbc.Driver";
    public static final String URL = "jdbc:mysql://localhost:3306/daydb";
    public static final String USERNAME = "root";
    public static final String PASSWORD = "root";
    /*
     * 创建连接池BasicDataSource
     */
    public static BasicDataSource dataSource = new BasicDataSource();
    //静态代码块
    static {
        //对连接池对象 进行基本的配置
        dataSource.setDriverClassName(DRIVER); // 这是要连接的数据库的驱动
        dataSource.setUrl(URL); //指定要连接的数据库地址
        dataSource.setUsername(USERNAME); //指定要连接数据的用户名
        dataSource.setPassword(PASSWORD); //指定要连接数据的密码
    }
    /*
     * 返回连接池对象
     */
    public static DataSource getDataSource(){
        return dataSource;
    }
}
dbcp的JDBCUtils
/*
 * 演示使用DBUtils工具  完成数据库表的增加操作
 */
public class Demo {
    // 插入功能 
    @Test
    public void insert(){
        try {
            //获取一个用来执行SQL语句的对象   QueryRunner
            QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
String sql = "INSERT INTO zhangwu(name,money,parent) VALUES(?,?,?)";
            Object[] params = {"股票收入", 5500, "收入"};    
             int line = qr.update(sql,params);
            //结果集处理
            System.out.println("line = " + line);
            
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    
    //删除功能
    @Test
    public void delete(){
        try {
            //创建一个QueryRunner对象,用来完成SQL语句的执行
            QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
            //执行SQL语句
            String sql = "DELETE FROM zhangwu WHERE name = ?";
            Object[] params = {"股票收入"};
            int line = qr.update(sql, params);
            //结果集的处理
            System.out.println("line="+line);
            
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    
    //更新功能
    @Test
    public void update(){
        try {
            //创建一个QueryRunner对象,用来完成SQL语句的执行
            QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
            //执行SQL语句
            String sql = "UPDATE zhangwu SET money = money+1000 WHERE name=?";
            Object[] params = {"股票收入"};
            int line = qr.update(sql, params);
            //结果集的处理
            System.out.println("line="+line);
            
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    
    //查询功能,将结果集中第一条记录封装到一个指定的javaBean中。
    @Test
    public void search(){
        try{
            //获取QueryRunner 
            QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
            //执行SQL语句
            String sql = "SELECT * FROM zhangwu";
            Object[] params = {};
            Product p = qr.query(sql, new BeanHandler<Product>(Product.class), params);
            //结果集处理
            System.out.println(p);
            
        } catch(SQLException e){
            throw new RuntimeException(e);
        }
    }
}
Demo

DBCP的BasicDataSource类常见配置项:

分类

属性

描述

必须项

driverClassName

数据库驱动名称

url

数据库的地址

username

用户名

password

密码

基本项(扩展)

maxActive

最大连接数量

minIdle

最小空闲连接

maxIdle

最大空闲连接

initialSize

初始化连接

必须项

driverClassName

数据库驱动名称

url

数据库的地址

username

用户名

password

密码

基本项

maxActive

最大连接数量

initialSize

连接池中初始化多少个Connection连接对象

扩展项

maxWait

超时等待时间以毫秒为单位 1000等于1

参考文档:http://commons.apache.org/proper/commons-dbcp/configuration.html

 

C3P0

c3p0-config.xml 文件中定义所有的连接信息。采用xml配置文件的方式, 程序会自动寻找配置文件。xml 的文件名固定为 3p0-config.xml 文件在 classpath 路径下,即 src 下, 就是类的加载路径。

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/数据库名</property>
        <property name="user">root</property>
        <property name="password">asd</property>
    </default-config>

    <named-config name="mysql">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/数据库名</property>
        <property name="user">root</property>
        <property name="password">asd</property>
    </named-config>

    <named-config name="oracle">
        ……
    </named-config>
</c3p0-config>
3p0-config.xml的基本配置

如果只有<default-config>则这样初始化数据源:
ComboPooledDataSource dataSource = new ComboPooledDataSource();
如果初始化指定名称的数据源如mysql, 则这样:
ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql");

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * JDBC的工具类:
 * @author admin
 *
 */
public class JDBCUtils2 {
    // 默认去类路径下去找 c3p0-config.xml
    private static final ComboPooledDataSource DATA_SOURCE =new ComboPooledDataSource();
    /**
     * 获得连接的方法
     */
    public static Connection getConnection(){
        Connection conn = null;
        try {
            conn = DATA_SOURCE.getConnection();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return conn;
    }
    
    public static DataSource getDataSource(){
        return DATA_SOURCE;
    }
    
    /**
     * 释放资源的方法
     */
    public static void release(ResultSet rs,Statement stmt,Connection conn){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            // 垃圾回收尽快回收对象.
            rs = null;
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            // 垃圾回收尽快回收对象.
            stmt = null;
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            // 垃圾回收尽快回收对象.
            conn = null;
        }
    }
    
    public static void release(Statement stmt,Connection conn){
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            // 垃圾回收尽快回收对象.
            stmt = null;
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            // 垃圾回收尽快回收对象.
            conn = null;
        }
    }
}
c3p0的JDBCUtils

c3p0的连接方式除了xml配置还有,set方法设置,和properties配置两种。

直接用set方法设置参数, 基本方法

ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUser("root");
dataSource.setPassword("asd");

调用的时候只需要在QueryRunner的构造方法里引用dataSource(以dbutils为例), 就像这样:
QueryRunner qr = new QueryRunner(dataSource);

当然也可以用dataSource获取一个连接, 像这样:
Connection conn = dataSource.getConnection();

然后查询的时候调用QueryRunner的无参构造函数, 像这样:
QueryRunner qr = new QueryRunner();

然后在调用查询方法时, 传入连接对象就可以了, 像这样:
User user = qr.query(conn, sql, new BeanHandler<User>(User.class));

采用.porperties属性文件的方式

固定文件名:c3p0.properties。文件在classpath路径下,即src下, 就是类的加载路径。

里面的配置如下
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/数据库名
c3p0.user=root
c3p0.password=asd

初始化数据源:
ComboPooledDataSource dataSource = new ComboPooledDataSource();

 

posted @ 2017-11-04 03:02  jaden好青年  阅读(140)  评论(0编辑  收藏  举报