JDBC 和数据库连接池基础应用(三)

一、数据库连接总结

1、使用DriverManager.getConnection(url, user, password)

JDBCUtils

public class JDBCUtils {
    //定义相关的属性(4个), 因为只需要一份,因此,我们做出static
    private static String user; //用户名
    private static String password; //密码
    private static String url; //url
    private static String driver; //驱动名

    //在static代码块去初始化
    static {

        try {
            Properties properties = new Properties();
            properties.load(new FileInputStream("src\\mysql.properties"));
            //读取相关的属性值
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            url = properties.getProperty("url");
            driver = properties.getProperty("driver");
        } catch (IOException e) {
            //在实际开发中,我们可以这样处理
            //1. 将编译异常转成 运行异常
            //2. 调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便.
            throw new RuntimeException(e);

        }
    }

    //连接数据库, 返回Connection
    public static Connection getConnection() {

        try {
            return DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            //1. 将编译异常转成 运行异常
            //2. 调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便.
            throw new RuntimeException(e);
        }
    }

    //关闭相关资源
    /*
        1. ResultSet 结果集
        2. Statement 或者 PreparedStatement
        3. Connection
        4. 如果需要关闭资源,就传入对象,否则传入 null
     */
    public static void close(ResultSet set, Statement statement, Connection connection) {

        //判断是否为null
        try {
            if (set != null) {
                set.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            //将编译异常转成运行异常抛出
            throw new RuntimeException(e);
        }

    }

}

 JDBCUtils使用操作增删改查SQL语句:

public class JDBCUtils_Use {


    @Test
    public void testSelect() {
        //1. 得到连接
        Connection connection = null;
        //2. 组织一个sql
        String sql = "select * from actor where id = ?";
        PreparedStatement preparedStatement = null;
        ResultSet set = null;
        //3. 创建PreparedStatement 对象
        try {
            connection = JDBCUtils.getConnection();
            System.out.println(connection.getClass()); //com.mysql.jdbc.JDBC4Connection
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, 1);//给?号赋值
            //执行, 得到结果集
            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 {
            //关闭资源
            JDBCUtils.close(set, preparedStatement, connection);
        }
    }

    @Test
    public void testDML() {//insert , update, delete

        //1. 得到连接
        Connection connection = null;
        //2. 组织一个sql
        String sql = "update actor set name = ? where id = ?";
        // 测试 delete 和 insert ,自己玩.
        PreparedStatement preparedStatement = null;
        //3. 创建PreparedStatement 对象
        try {
            connection = JDBCUtils.getConnection();

            preparedStatement = connection.prepareStatement(sql);
            //给占位符赋值
            preparedStatement.setString(1, "周星驰");
            preparedStatement.setInt(2, 4);
            //执行
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtils.close(null, preparedStatement, connection);
        }
    }
}

 2、数据库连接池

C3P0:

//1. 创建一个数据源对象,引入相关jar包,使用ComboPooledDataSource()创建对象获得多个连接的连接池

ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();

//2、注意:连接管理是由 comboPooledDataSource 来管理                     comboPooledDataSource.setDriverClass(driver);

         comboPooledDataSource.setJdbcUrl(url);

         comboPooledDataSource.setUser(user);                     comboPooledDataSource.setPassword(password);

3、设置初始化连接数

comboPooledDataSource.setInitialPoolSize(10);

     最大连接数

comboPooledDataSource.setMaxPoolSize(50);

4、连接这个方法就是从 DataSource 接口实现的:

Connection connection = comboPooledDataSource.getConnection();

或者使用配置文件:

ComboPooledDataSource comboPooledDataSource

                                        = new ComboPooledDataSource("pool_name");

        建立连接与上同,不用单独设置参数(配置文件)连接方法从 DataSource 接口实现:

Connection connection = comboPooledDataSource.getConnection();

 Druid(德鲁伊):

1、加入 Druid jar包,加入 配置文件 druid.properties , 将该文件拷贝项目的src目录

2、创建一个数据源对象,使用DruidDataSourceFactory.createDataSource(properties);获得,创建DataSource对象,德鲁伊数据源工厂:

DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

3、连接这个方法就是从 DataSource 接口实现的:

        Connection connection = dataSource.getConnection();

         无论是C3P0的ComboPooledDataSource还是Druid的DruidDataSourceFactory都实现了DataSource接口,可以由动态绑定进行定义声名。可以将连接和关闭写成一个工具类

        但是只是连接的问题解决了,执行SQL语句仍需要connection.ProparedStatement(sql)

sql拱顶不能通过参数传入。

        preparedStatement = connection.prepareStatement(sql);

        //给第一个?号赋值为1        

        preparedStatement.setInt(1, 1);

        //执行, 得到结果集

        set =preparedStatement.executeQuery();

二、 Apache—DBUtils总结

DbUtils类是Apache组织开发提供,解决了结果集复用(javabean+集合接收结果集)以及连接执行返回一条语句即可。

1、使用 DBUtils 类和接口 , 先引入DBUtils 相关的jar , 加入到本Project

2、得到 连接 (druid)

        Connection connection = JDBCUtilsByDruid.getConnection();

3、 创建 QueryRunner

        QueryRunner queryRunner = new QueryRunner();

4、之前connect.PrepareStatement(sql)和ResultSet以及PrepareStatement.setInt(1,1)

connection:Druid工具得到的连接

sql:要执行的查询语句

new BeanListHandler<>(Actor.class):接收查询结果集到集合中,且集合元素为Actor类型

1:就是给 sql 语句中的? 赋值,可以有多个值,因为是可变参数Object... params

List<Actor> list

           = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);

目前:建立连接使用Druid(德鲁伊)连接池,执行SQL以及保存结果集使用Apache中的DBUtils工具

即:Apache-DBUtils+Druid简化了JDBC的开发

三、DAO(Data Access Object数据访问对象)

1、DAO 和增删改查通用方法-BasicDao

1.1、问题引入

虽然Apache-DBUtils+Druid简化了JDBC的开发,但还有不足:

1、SQL语句固定,不能通过参数传入,通用性不好,需要进行改进,更方便执行增删改查

2、对于select操作,如果有返回值,返回类型不能固定,需要使用泛型

3、将来的表很多,业务需求复杂,不可能只靠一个Java类完成

因此,引出DAO

使用的依然是Apache-DBUtils+Druid,只不过再B阿思翠DAO类中有各自的函数取调用Apache-DBUtils下的QueryRunner类下的各种操作方法,实现封装。

1.2、基本说明 

1、DAO:data access object数据访问对象

2、这样的通用类,称为BasicDAO,是专门和数据交互的,即完成对数据库(表)的CRUD操作

3、再BasicDAO基础上,实现一张表对应一个DAO,更好的完成功能。比如Customer表--对应Customer.java类(javabean、domain)---对应一个CustomerDAO.java,,即操作Customer表使用CustomerDAO类操作,操作Goods表使用GoodsDAO类操作,他们都继承于BasicDAO类

 简单示例:

1、utils包----放工具类(连接和关闭数据库)

2、domain---存放表中的属性类,如admin表,有用户名列和密码列,domian包里有一个Admin类,有属性userNmae和password两个属性对应这表的字段,用来接收结果集存放在集合中,复用。

3、dao包---存放XxxDAO和BasicDAO类,XxxDAO对应某张表,也对应某个domain中的类

4、test---写测试类

utils包:JDBCUtilsByDruid---通过Druid(德鲁伊)DataSource接口连接池建立的连接和关闭的工具类

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) {
            e.printStackTrace();
        }

    }

    //编写getConnection方法
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    //关闭连接, 老师再次强调: 在数据库连接池技术中,close 不是真的断掉连接
    //而是把使用的Connection对象放回连接池
    public static void close(ResultSet resultSet, Statement statement, Connection connection) {

        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

 domain包---Actor类(Javabean,POJO,Domian对象),操作Actor表,属性和Actor表中各字段对应

public class Actor { //Javabean, POJO, Domain对象

    private Integer id;
    private String name;
    private String sex;
    private Date borndate;
    private String phone;

    public Actor() { //一定要给一个无参构造器[反射需要]
    }

    public Actor(Integer id, String name, String sex, Date borndate, String phone) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.borndate = borndate;
        this.phone = phone;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    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;
    }

    public Date getBorndate() {
        return borndate;
    }

    public void setBorndate(Date borndate) {
        this.borndate = borndate;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "\nActor{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", borndate=" + borndate +
                ", phone='" + phone + '\'' +
                '}';
    }
}

dao包--- 存放ActorDAO和BasicDAO类---实现对Actor表操作

连接由Druid连接池建立,操作由Apache--dautils包下的QueryRunner类执行

  1. BasicDAO类中有方法update(Sting sql,Object...parameters),该方法下调用QueryRunner的update(connection, sql, parameters)方法实现增删改的操作。
  2. BasicDAO类中有方法:public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters),返回的是一个list集合列表,泛型表示列表存放的类型,该方法下调用QueryRunner的query(connection, sql, new BeanListHandler<T>(clazz), parameters
    )方法
    实现查找并返回结果集的集合
  3. BasicDAO类中有方法:public T querySingle(String sql, Class<T> clazz, Object... parameters),返回的是的那行查询的结果集,因此不用集合保存。该方法下将调用QueryRunner的query(connection, sql, new BeanHandler<T>(clazz), parameters);
  4. 查询单行单列的数据
public class BasicDAO<T> { //泛型指定具体类型
//    Apeche---DBUtils
    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);
        }

    }

    //返回多个对象(即查询的结果是多行), 针对任意表

    /**
     *
     * @param sql sql 语句,可以有 ?
     * @param clazz 传入一个类的Class对象 比如 Actor.class
     * @param parameters 传入 ? 的具体的值,可以是多个
     * @return 根据Actor.class 返回对应的 ArrayList 集合
     */
    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);
        }
    }

}
public class ActorDAO extends BasicDAO<Actor> {
    //1. 就有 BasicDAO 的方法
    //2. 根据业务需求,可以编写特有的方法.
}

ActorDAO继承BasicDAO类,拥有了BasicDAO的所有方法

test包---测试类 TestDAO

操作Actor表就创建ActorDAO对象(继承了BasicDAO,动态绑定机制)

public class TestDAO {

    //测试ActorDAO 对actor表crud操作
    @Test
    public void testActorDAO() {

        ActorDAO actorDAO = new ActorDAO();
        //1. 查询,动态绑定机制
        List<Actor> actors = actorDAO.queryMulti("select * from actor where id >= ?", Actor.class, 1);
        System.out.println("===查询结果===");
        for (Actor actor : actors) {
            System.out.println(actor);
        }

        //2. 查询单行记录
        Actor actor = actorDAO.querySingle("select * from actor where id = ?", Actor.class, 6);
        System.out.println("====查询单行结果====");
        System.out.println(actor);

        //3. 查询单行单列
        Object o = actorDAO.queryScalar("select name from actor where id = ?", 6);
        System.out.println("====查询单行单列值===");
        System.out.println(o);

        //4. dml操作  insert ,update, delete
        int update = actorDAO.update("insert into actor values(null, ?, ?, ?, ?)", "张无忌", "男", "2000-11-11", "999");

        System.out.println(update > 0 ? "执行成功" : "执行没有影响表");

    }
}

四、作业练习 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值