一、JDBC 快速入门

JDBC 第一弹
JDBC 第二弹

1.1 什么是 JDBC?

Java数据库连接,(Java Database Connectivity,简称 JDBC )是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。 —— 来源于百度词条

1.2 为什么要学习 JDBC?

我们存储数据总不能全部存进 文件里,然后使用 FileInputStream 和 FileOutPutStream 进行读和写的操作把,这个时候数据库就来了,那么什么是数据库呢?(数据库:即组织,存储 和 管理数据的仓库)。这样有了数据库,我们就可以把结构化的数据存储进数据库中,有了数据库这个东西,接下来我们就可以使用 JDBC 操作数据库啦!

1.3 学习 JDBC 之前需要有哪些准备知识呢?

  1. 使用 JDBC 得先学习什么是数据库
  2. 并且会熟练使用 sql 语句进行 CRUD 操作
  3. 掌握一种关系型数据库的使用(mysql)
  4. 了解 JDBC 的基本步骤

二、编写你的第一个 JDBC 程序

2.1 导入一个外部 jar 包

我们连接 mysql 数据库,所以需要导入 mysql 的驱动包,我的 mysql 版本是 5.7 的,所以使用 版本第一点的 驱动即可。
image.png

这个 jar 包是从网上下载下来的,它是由 数据库开发商提供的,专门用来连接 java 的驱动包,这个是必不可少的。

2.2 编写一个简单的 jdbc 程序

我这个程序的作用是 查询 bank 数据库中的,user 表

  1. import java.sql.*;
  2. public class DBUTIL {
  3. private static final String URL = "jdbc:mysql://localhost:3306/bank";
  4. private static final String USERNAME = "root";
  5. private static final String PASSWORD = "root";
  6. /**
  7. * 对数据库中的数据进行增删改查 CRUD
  8. * sql: insert、delete、update、select
  9. *通过 java 程序来操作数据库中的数据 jdbc
  10. * 在 java 中写 sql,java “将写好的 sql 交给数据库运行” 从而操作数据
  11. * 重点:将写好的 sql 交给数据库运行
  12. * */
  13. public static void main(String[] args) throws ClassNotFoundException, SQLException {
  14. //1. 加载驱动程序
  15. Class.forName("com.mysql.jdbc.Driver");
  16. //2. 获取数据库的连接
  17. Connection coon = DriverManager.getConnection(URL,USERNAME,PASSWORD);
  18. //3. 通过数据库的连接操作数据库,实现增删改查
  19. Statement stmt = (Statement) coon.createStatement();
  20. // 查用 executeQuery,其它用 execute
  21. ResultSet rs = stmt.executeQuery("select * from user");//返回 ResultSet 对象
  22. /**
  23. * 1. 加载数据的驱动(先决条件)
  24. * 2. 将当前的 java 程序与数据库建立连接
  25. * 3. 将 sql 交给数据库运行
  26. * 4. 处理结果
  27. * 5. 关闭资源(首尾)
  28. * */
  29. //打印数据
  30. System.out.println("username password status phone registertime");
  31. while(rs.next()) {
  32. //返回字符串, 两种查询的方式
  33. // System.out.println(rs.getString("username")+" "+rs.getString("password"));
  34. System.out.println(rs.getString(1)+ " "+ rs.getString(2)+" "+rs.getInt(3)+ " "+ rs.getInt(4)+" "+rs.getTimestamp(5));
  35. }
  36. rs.close();
  37. stmt.close();
  38. coon.close();
  39. }
  40. }

数据库中查询的结果:
image.png
jdbc 查到的数据
image.png

三、JDBC 的封装

3.1 封装等级(一级)

此等级需要用户编写重要的 SQL 语句即可完成

  1. import java.sql.*;
  2. public class BaseDao {
  3. private String Driver = "com.mysql.jdbc.Driver";
  4. private static final String URL = "jdbc:mysql://localhost:3306/bank?useUnicode=true&characterEncoding=utf8";
  5. private static final String USERNAME = "root";
  6. private static final String PASSWORD = "root";
  7. private Connection con = null;
  8. // 获取连接
  9. public PreparedStatement getConnect(String sql) throws SQLException {
  10. PreparedStatement ps = null;
  11. try {
  12. Class.forName(Driver);
  13. con = DriverManager.getConnection(URL,USERNAME,PASSWORD);
  14. ps = con.prepareStatement(sql);
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. con.rollback();
  18. }
  19. return ps;
  20. }
  21. // 关闭连接
  22. public void colesd(PreparedStatement ps, ResultSet set) throws SQLException {
  23. if (ps!=null) {
  24. ps.close();
  25. }
  26. if (set!=null) {
  27. set.close();
  28. }
  29. if (con!=null) {
  30. con.close();
  31. }
  32. }
  33. }

3.2 封装等级(二级)

完成 增删改 和 查的封装

  1. import java.sql.Connection;
  2. import java.sql.DriverManager;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. /**
  7. * @author Gorit
  8. * @date 2019年12月13日
  9. * @Task JDBC 使用 BaseDao 进行封装
  10. * @next 使用 jdbc.properties 进行全局封装
  11. * @资料:参考 11-25 的资料
  12. * */
  13. public class BaseDao {
  14. //导入 java.sql 包下的类
  15. protected Connection conn = null;
  16. protected PreparedStatement pstmt = null;
  17. protected ResultSet rs = null;
  18. //1.得到连接对象
  19. public boolean getConn() {
  20. boolean flag = false;
  21. //1. 加载驱动 com.mysql.jdbc.Driver
  22. try {
  23. //jdbc.driver = com.mysql.jdbc.Driver
  24. //jdbc.url = jdbc:mysql://localhost:3306/bank
  25. //jdbc.username=root
  26. //jdbc.password=root
  27. Class.forName("com.mysql.jdbc.Driver");
  28. //2. 创建连接对象
  29. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bank?userUnicode=true&characterEncoding=utf8","root","root");
  30. flag = true;//标记
  31. } catch (ClassNotFoundException | SQLException e) {
  32. // TODO: handle exception
  33. e.printStackTrace();
  34. }
  35. return flag;
  36. }
  37. // 2 executeUpdate--增删改 sql 参数不同
  38. public int executeUpdate(String sql, Object[] params) {
  39. int result = 0;
  40. if (getConn()) {//连接成功
  41. try {
  42. pstmt = conn.prepareStatement(sql);
  43. for (int i = 0; i < params.length; i++) {
  44. pstmt.setObject(i + 1, params[i]);
  45. }
  46. result = pstmt.executeUpdate();
  47. } catch (SQLException e) {
  48. // TODO Auto-generated catch block
  49. e.printStackTrace();
  50. } //得到pstmt对象
  51. }
  52. return result;
  53. }
  54. // 3 executeQuery 语句查询
  55. public ResultSet executeQuery(String sql, Object[] params) {
  56. if (getConn()) { //连接成功
  57. try {
  58. pstmt = conn.prepareStatement(sql);
  59. for (int i = 0; i < params.length; i++) {
  60. pstmt.setObject(i + 1, params[i]);
  61. }
  62. rs = pstmt.executeQuery(); //执行查询工作
  63. } catch (SQLException e) {
  64. // TODO: handle exception
  65. e.printStackTrace();
  66. }
  67. }
  68. return rs;
  69. }
  70. //4 释放资源,关闭连接
  71. public void closeResource() {
  72. //按顺序关闭
  73. if (rs != null) {
  74. try {
  75. rs.close();
  76. } catch (SQLException e) {
  77. // TODO: handle exception
  78. e.printStackTrace();
  79. }
  80. }
  81. if (pstmt != null) {
  82. try {
  83. pstmt.close();
  84. } catch (SQLException e) {
  85. // TODO: handle exception
  86. e.printStackTrace();
  87. }
  88. }
  89. if (conn != null) {
  90. try {
  91. conn.close();
  92. } catch (SQLException e) {
  93. // TODO: handle exception
  94. e.printStackTrace();
  95. }
  96. }
  97. }
  98. }

四、C3P0以及Druid数据库连接池

4.1什么是数据库连接池?

概念:其实就是一个容器(集合),存放数据库连接的容器。 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户访问数据库时,从容器中获取连接对象,用 户访问完后,会将连接对象还给容器

注意:在使用C3P0和Druid时都要先导入相应的jar包

4.2C3P0连接池

C3P0配置文件的注意事项

  • 名称:c3p0.properties或者c3p0-config.xml
  • 路径:直接将文件放在src目录下

C3P0的基本用法

  1. //1.创建数据库连接池对象
  2. DataSource ds = new ComboPooledDataSource();
  3. //2. 获取连接对象
  4. Connection conn = ds.getConnection();

4.3Durid连接池(常用)

利用Druid进行jdbc封装

package per.myself.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtils {
    private static DataSource ds;

    static {
        try {
            //1.加载配置对象
            Properties pro = new Properties();
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2.获取DataSource
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

        //获取连接
        public static Connection getConnection() throws SQLException {
            return ds.getConnection();
        }

        //释放资源

    public static void close(Statement stmt,Connection conn) {
//        if(stmt!=null){
//            try {
//                stmt.close();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }
//
//        if(conn!=null){
//            try {
//                conn.close();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }
        close(null,stmt,conn);
    }


    public static void close(ResultSet res, Statement stmt, Connection conn) {

        if(res!=null){
            try {
                res.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    public static DataSource getDataSource(){
        return  ds;
    }
}

五、Spring JDBC:JDBC Template

5.1JDBC Template方法的CRUD操作

  1. update():执行DML语句。增、删、改语句
  2. queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合

注意:这个方法查询的结果集长度只能是1

  1. queryForList():查询结果将结果集封装为list集合

注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

  1. query():查询结果,将结果封装为JavaBean对象

query的参数:RowMapper
一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
new BeanPropertyRowMapper<类型>(类型.class)queryForObject:查询结果,将结果封装为对象
一般用于聚合函数的查询

5.2JDBC Template实现对数据库的操作

这里是对tb_account进行操作,表的数据有id,userName,password

package per.myself.jdbctemplate;

import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import per.myself.entity.Account;
import per.myself.utils.JDBCUtils;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class JdbcTemplateDemo002 {

    //Junit单元测试,可以让方法独立执行


    //1. 获取JDBCTemplate对象
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    /**
     * 1. 修改1号数据的 salary 为 10000
     */
    @Test
    public void test1(){

        //2. 定义sql
        String sql = "update tb_account set password = 10000 where id = 3";
        //3. 执行sql
        int count = template.update(sql);
        System.out.println(count);
    }

    /**
     * 2. 添加一条记录
     */
    @Test
    public void test2(){
        String sql = "insert into tb_account values(?,?,?)";
        int count = template.update(sql, null, "郭靖", "asdsa");
        System.out.println(count);

    }

    /**
     * 3.删除刚才添加的记录
     */
    @Test
    public void test3(){
        String sql = "delete from tb_account where id = ?";
        int count = template.update(sql, 2);
        System.out.println(count);
    }

    /**
     * 4.查询id为1001的记录,将其封装为Map集合
     * 注意:这个方法查询的结果集长度只能是1
     */
    @Test
    public void test4(){
        String sql = "select * from tb_account where id = ? ";
        Map<String, Object> map = template.queryForMap(sql, 1);
        System.out.println(map);
        //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}

    }

    /**
     * 5. 查询所有记录,将其封装为List
     */
    @Test
    public void test5(){
        String sql = "select * from tb_account";
        List<Map<String, Object>> list = template.queryForList(sql);

        for (Map<String, Object> stringObjectMap : list) {
            System.out.println(stringObjectMap);
        }
    }

    /**
     * 6. 查询所有记录,将其封装为Emp对象的List集合
     */

    @Test
    public void test6(){
        String sql = "select * from tb_account";
        List<Account> list = template.query(sql, new RowMapper<Account>() {

            @Override
            public Account mapRow(ResultSet rs, int i) throws SQLException {
                Account emp = new Account();
                int id = rs.getInt("id");
                String userName = rs.getString("userName");
                String password = rs.getString("password");

                emp.setId(id);
                emp.setUserName(userName);
                emp.setPassword(password);


                return emp;
            }
        });


        for (Account acc : list) {
            System.out.println(acc);
        }
    }

    /**
     * 6. 查询所有记录,将其封装为Emp对象的List集合
     */

    @Test
    public void test6_2(){
        String sql = "select * from tb_account";
        List<Account> list = template.query(sql, new BeanPropertyRowMapper<Account>(Account.class));
        for (Account acc : list) {
            System.out.println(acc);
        }
    }

    /**
     * 7. 查询总记录数
     */

    @Test
    public void test7(){
        String sql = "select count(id) from tb_account";
        Long total = template.queryForObject(sql, Long.class);
        System.out.println(total);
    }

}