JDBC数据库编程

 

目录

一 传统的JDBC编程,操作数据库的方式

1 JDBC介绍

2 JDBC开发说明

3 DriverManager类

4 Connection接口

5 Statement接口

6 ResultSet接口

 7 JDBC访问数据库的步骤

8 编程实例

二 数据库工具类 JdbcUtils

1 工具类的创建

2 用户登录案例说明JdbcUtils的使用方法

3 SQL注入问题

三 PreparedStatement接口

1 PreparedStatement 和 Statement 区别

 2 使用 PreparedStatement 改写上面的登录程序,看有没有 SQL 注入的情况

3 使用 PreparedStatement 查询一条数据,封装成一个学生 Student 对象

 4 将多条记录封装成集合 List,集合中每个元素是一个 JavaBean 实体类

 5 PreparedStatement 执行 DML 操作

四 JDBC中事务的处理

1 Connection接口中关于事务的方法

2 以转账事务为例说明用法

五 数据库连接池

1 介绍:

2 C3P0:数据库连接池技术

3 Druid:数据库连接池实现技术

4 定义一个工具类,方便调用

5 Spring JDBC


一 传统的JDBC编程,操作数据库的方式

JDBC介绍

JDBC是Java访问数据库的标准规范,真正操作数据库还需要具体的实现类,也就是数据库驱动

使用 JDBC 的好处:

  • 程序员如果要开发访问数据库的程序,只需要会调用 JDBC 接口中的方法即可,不用关注类是如何实现的。
  • 使用同一套 Java 代码,进行少量的修改就可以访问其他 JDBC 支持的数据库。

2 JDBC开发说明

使用JDBC开发使用到的包

JDBC核心的API

导入驱动jar包 

在开始使用前需要先导入驱动jar包,mysql-connector-java-5.1.37-bin.jar,并添加到库

需要加载和注册驱动

3 DriverManager类

作用是管理和注册驱动,创建数据库的连接

类中的方法

使用JDBC连接数据库的四个参数

连接数据库的URL地址格式

乱码的处理

如果数据库出现乱码,可以指定参数: ?characterEncoding=utf8,表示让数据库以 UTF-8 编码来处理数据。jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8

4 Connection接口

作用,代表一个连接对象

5 Statement接口

作用:代表一条语句对象,用于发送SQL语句给服务器,执行静态SQL语句并返回生成结果对象。

方法

释放资源

  1. 需要释放的对象:ResultSet 结果集,Statement 语句,Connection 连接
  2. 释放原则:先开的后关,后开的先关。ResultSet->Statement->Connection
  3. 放在哪个代码块中:finally 块

6 ResultSet接口

作用:封装数据库查询的结果集,对结果集进行遍历,取出每一条记录。

 方法

 常用数据类型转换表

其中 java.sql.DateTimeTimestamp(时间戳),三个共同父类是:java.util.Date

 7 JDBC访问数据库的步骤

  • 注册和加载驱动(可以省略)
  • 获取连接 Connection
  • 获取 Statement 对象
  • 使用 Statement 对象执行 SQL 语句
  • 返回结果集
  • 释放资源

8 编程实例

需求:使用JDBC在MySQL中创建一张学生表,执行的DDL操作

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

public class JDBCTest {
    public static void main(String[] args) {
        /**
         * 执行DDL操作,在MySQL数据库的test中创建一张学生表
         * id int primary key auto_increment,
         * name varchar(20) not null,
         * gender boolean,
         * birthday date
         */


        Connection conn = null;
        Statement statement = null;
        try {
            //1.创建连接
            conn = DriverManager.getConnection("jdbc:mysql:///test","root","root");
            //2.通过连接对象得到语句对象
            statement = conn.createStatement();
            //3.通过语句对象发送SQL语句给服务器,并且执行SQL
            statement.executeUpdate("create table student(id int PRIMARY  KEY  auto_increment,"+
                    "name VARCHAR (20) not null,gender boolean,birthday date)");
            //4.返回影响行数(DDL没有返回值)
            System.out.println("创建表成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.释放资源,关闭之前要先判断
            if(statement != null){
                try{
                    statement.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
            }
            if(conn != null){
                try{
                    conn.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
            }
        }

    }
}

需求:执行DML操作,向学生表中添加 4 条记录,主键是自动增长

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

public class DMLTest {
    public static void main(String[] args) throws SQLException {
        /**
         * 向学生表中添加4条记录,主键是自增长
         * 步骤:
         * 1. 创建连接对象
         * 2. 创建Statement语句对象
         * 3. 执行SQL语句 executeUpdate(sql)
         * 4. 返回影响的行数
         * 5.释放资源
         */
        //创建连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql:///test","root","root");
        //创建Statement语句对象
        Statement statement = connection.createStatement();
        //执行SQL语句并返回影响的行数
        int count = 0;
        count += statement.executeUpdate("insert into student values(null,'孙悟空',1,'1993-03-24')");
        count += statement.executeUpdate("insert into student values(null,'白骨精',0,'1995-06-13')");
        count += statement.executeUpdate("insert into student values(null,'猪八戒',1,'1903-03-24')");
        count += statement.executeUpdate("insert into student values(null,'嫦娥',0,'1993-03-11')");
        System.out.println("插入了" + count + "条记录");
        //释放资源
        statement.close();
        connection.close();
    }
}

查看数据库,发现执行插入语句成功

 

 需求:确保数据库中有 3 条以上的记录,查询所有的学员信息

import java.sql.*;

public class DQLTest {
    public static void main(String[] args) throws SQLException {
        /**
         * 需求 确保数据库中有 3 条以上的记录,查询所有的学员信息
         * 步骤
         * 1.得到连接对象
         * 2.得到语句对象
         * 3.执行 SQL 语句得到结果集 ResultSet 对象
         * 4.循环遍历取出每一条记录
         * 5.输出的控制台上
         * 6.释放资源
         */
        //1.创建连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql:///test","root","root");
        //2.创建Statement语句对象
        Statement statement = connection.createStatement();
        //3.执行SQL语句得到结果集ResultSet对象
        ResultSet resultSet = statement.executeQuery("select * from student");
        //4.循环遍历取出每一条记录
        while(resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            boolean gender = resultSet.getBoolean("gender");
            Date birthday = resultSet.getDate("birthday");
            //5.输出到控制台
            System.out.println("编号:"+id+",姓名:"+name+",性别:"+gender+",生日:"+birthday);
        }
        //6.释放资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

控制台打印输出的结果

 关于 ResultSet 接口中的注意事项:

  • 如果光标在第一行之前,使用 rs.getXX()获取列值,报错:Before start of result set
  • 如果光标在最后一行之后,使用 rs.getXX()获取列值,报错:After end of result set
  • 使用完毕以后要关闭结果集 ResultSet,再关闭 Statement,再关闭 Connection

二 数据库工具类 JdbcUtils

如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用。

1 工具类的创建

 创建类JdbcUtils包含3个方法

  • 可以把几个字符串定义成常量:用户名,密码,URL,驱动类
  • 得到数据库的连接:getConnection()
  • 关闭所有打开的资源 close(Connection conn, Statement stmt)close(Connection conn, Statement stmt, ResultSet rs)
import java.sql.*;

/**
 * 访问数据的工具类
 */
public class JdbcUtils {

    //把几个字符串定义为常量:用户名,密码,URL,驱动类
    private static final String USER = "root";
    private static final String PWD = "root";
    private static final String URL = "jdbc:mysql://localhost:3306/test";
    private static final String DRIVER = "com.mysql.jdbc.Driver";

    /**
     * 注册驱动
     */
    static {
        try{
            Class.forName(DRIVER);
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
    }

    /**
     * 得到数据库的连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException{
        return DriverManager.getConnection(URL,USER,PWD);
    }

    /**
     * 关闭所有打开的资源
     * @param conn
     * @param statement
     */
    public static void close(Connection conn, Statement statement){
        if(statement != null){
            try{
                statement.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if(conn != null){
            try{
                conn.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭所有打开的资源
     * @param connection
     * @param statement
     * @param resultSet
     */
    public static  void close(Connection connection, Statement statement, ResultSet resultSet){
        if(resultSet != null){
            try{
                resultSet.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        close(connection,statement);
    }
}

2 用户登录案例说明JdbcUtils的使用方法

需要有一张用户表和几条用户的记录

#创建用户表

CREATE TABLE USER(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(20),
    PASSWORD VARCHAR(20)
);

#在表中添加记录

INSERT INTO USER VALUES(NULL,'jack','123'),(NULL,'rose','456');

#登录,SQL中大小写不敏感

SELECT * FROM USER WHERE NAME='JACK' AND PASSWORD='123';

#登陆失败

SELECT * FROM USER WHERE NAME='JACK' AND PASSWORD='333';

使用 Statement 字符串拼接的方式实现用户的登录 , 用户在控制台上输入用户名和密码。
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class LoginTest {
     /**
     * 步骤:
     * 1.得到用户从控制台上输入的用户名和密码来查询数据库
     * 2.写一个登录的方法,包括:
     *      a.通过工具类得到连接
     *      b.创建语句对象,使用拼接字符串的方式生成 SQL 语句
     *      c.查询数据库,如果有记录则表示登录成功,否则登录失败
     *      d.释放资源
     * @param args
     */
    public static void main(String[] args) {
        //从控制台上输入用户名和密码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String name = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();
        login(name,password);
    }

    /**
     * 登录方法
     * @param name
     * @param password
     */
    public static void login(String name,String password){
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try{
            //通过工具类得到连接
            connection = JdbcUtils.getConnection();
            //创建语句对象
            statement = connection.createStatement();
            //使用拼接字符串的方式生成SQL语句
            String sql = "select * from user where name='"+name+"' and password='"+password+"'";
            System.out.println(sql);
            //查询数据库,如果有记录,则表示登录成功,否则登陆失败
            resultSet = statement.executeQuery(sql);
            if(resultSet.next()){
                System.out.println("登录成功,欢迎您:" + name);
            }else{
                System.out.println("登陆失败");
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            //释放资源
            JdbcUtils.close(connection,statement,resultSet);
        }
    }
}

3 SQL注入问题

对于上面的sql语句查询的方式,使用字符串拼接参数,当输入下面的密码后,也可以成功登录。因此, 我们让用户输入的密码和 SQL 语句进行字符串拼接。用户输入的内容作为了 SQL 语句语法的一部分,改变了 原有 SQL 真正的意义,以上问题称为 SQL 注入。要解决 SQL 注入就不能让用户输入的密码和我们的 SQL 语句进行简单的字符串拼接。

三 PreparedStatement接口

PreparedStatement 和 Statement 区别

PreparedStatement 是 Statement 接口的子接口,继承于父接口中所有的方法。它是一个预编译的SQL 语句,和Statement对象的区别是:

  • Statement对象每执行一条SQL语句都会先将SQL语句发送给数据库,数据库先编译SQL,再执行。如果有1万条类似的SQL语句,数据库要编译1万次,执行1万次,效率低。
  • PreparedStatement会将SQL语句发送给数据库预编译,PreparedStatement会引用编译后的结果。可以多次传入不同的参数给PreparedStatement对象并执行。如果有1万条类似的插入语句,数据库只需要编译一次,传入1万次不同的参数并执行,减少了SQL语句的编译次数,提高了执行效率。

作用

  • 因为有预先编译的功能,提高 SQL 的执行效率。
  • 可以有效的防止 SQL 注入的问题,安全性更高
Connection 创建 PreparedStatement 对象

 PreparedStatement 接口中的方法:

 

  PreparedStatement 中设置参数的方法:

 2 使用 PreparedStatement 改写上面的登录程序,看有没有 SQL 注入的情况

import java.sql.*;
import java.util.Scanner;

public class LoginTest {
    /**
     * 使用PreparedStatement改写登录程序,解决SQL注入的问题
     * 步骤:
     * 1.编写SQL语句,未知内容使用?占位:"SELECT * FROM user WHERE name=? AND password=?";
     * 2.获得 PreparedStatement 对象
     * 3.设置实际参数:setXxx(占位符的位置, 真实的值)
     * 4.执行参数化 SQL 语句
     * 5.关闭资源
     * @param args
     */

    public static void main(String[] args) {
        //从控制台上输入用户名和密码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String name = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();
        login(name,password);
    }

    /**
     * 登录方法
     * @param name
     * @param password
     */
    public static void login(String name,String password){
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try{
            //通过工具类得到连接
            connection = JdbcUtils.getConnection();
            //写成登录的SQL语句,没有单引号,采用占位符的方式(未知内容用?占位)
            String sql = "select * from user where name=? and password=? ";
            //得到语句对象
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            //设置参数
            preparedStatement.setString(1,name);
            preparedStatement.setString(2,password);
            //查询数据库,如果有记录,则表示登录成功,否则登陆失败
            resultSet = preparedStatement.executeQuery();
            if(resultSet.next()){
                System.out.println("登录成功,欢迎您:" + name);
            }else{
                System.out.println("登陆失败");
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            //释放资源
            JdbcUtils.close(connection,statement,resultSet);
        }
    }
}

3 使用 PreparedStatement 查询一条数据,封装成一个学生 Student 对象

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

public class JdbcStudent {
    public static void main(String[] args) throws SQLException {
        //创建学生对象
        Student student = new Student();
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement("select * from student where id=? ");
        //设置参数
        preparedStatement.setInt(1,2);
        ResultSet resultSet = preparedStatement.executeQuery();
        if(resultSet.next()){
            //封装成一个学生对象
            student.setId(resultSet.getInt("id"));
            student.setName(resultSet.getString("name"));
            student.setGender(resultSet.getBoolean("gender"));
            student.setBirthday(resultSet.getDate("birthday"));
        }
        //释放资源
        JdbcUtils.close(connection,preparedStatement,resultSet);
        //打印数据
        System.out.println(student.toString());
    }
}

 4 将多条记录封装成集合 List<Student>,集合中每个元素是一个 JavaBean 实体类

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class StudentList {
    public static void main(String[] args) throws SQLException {
        //创建一个集合
        List<Student> students = new ArrayList<>();
        Connection connection = JdbcUtils.getConnection();
        String sql = "select * from student";
        PreparedStatement ps = connection.prepareStatement(sql);
        //没有参数替换
        ResultSet resultSet = ps.executeQuery();
        while(resultSet.next()){
            //每次循环是一个学生对象
            Student student = new Student();
            //封装成一个学生对象
            student.setId(resultSet.getInt("id"));
            student.setName(resultSet.getString("name"));
            student.setGender(resultSet.getBoolean("gender"));
            student.setBirthday(resultSet.getDate("birthday"));
            //把数据放到集合中
            students.add(student);
        }
        //关闭连接
        JdbcUtils.close(connection,ps,resultSet);
        //打印数据
        for(Student stu:students){
            System.out.println(stu.toString());
        }
    }
}

 

 5 PreparedStatement 执行 DML 操作

package com.itcast.jdbc;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class DMLPSTest {
    public static void main(String[] args) throws SQLException {
//        insert();
//        update();
        delete();
    }
    //插入记录
    private static void insert() throws SQLException {
        Connection connection = JdbcUtils.getConnection();
        String sql = "insert into student values(null,?,?,?)";
        PreparedStatement ps = connection.prepareStatement(sql);
        ps.setString(1,"小白龙");
        ps.setBoolean(2,true);
        ps.setDate(3, Date.valueOf("1999-11-11"));
        int row = ps.executeUpdate();
        System.out.println("插入了" + row +"条记录");
        JdbcUtils.close(connection,ps);
    }

    //更新记录:换名字和生日
    private static void update() throws SQLException {
        Connection connection = JdbcUtils.getConnection();
        String sql = "update student set name=?,birthday=? where id=?";
        PreparedStatement ps = connection.prepareStatement(sql);
        ps.setString(1,"黑熊怪");
        ps.setDate(2, Date.valueOf("1999-03-23"));
        ps.setInt(3,5);
        int row = ps.executeUpdate();
        System.out.println("更新了" + row +"条记录");
        JdbcUtils.close(connection,ps);
    }

    //删除记录,删除第5条记录
    private static void delete() throws SQLException {
        Connection connection = JdbcUtils.getConnection();
        String sql = "delete from student where id=?";
        PreparedStatement ps = connection.prepareStatement(sql);
        ps.setInt(1,5);
        int row = ps.executeUpdate();
        System.out.println("删除了" + row +"条记录");
        JdbcUtils.close(connection,ps);
    }
}

四 JDBC中事务的处理

1 Connection接口中关于事务的方法

2 以转账事务为例说明用法

#创建表
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
balance DOUBLE
);
-- 添加数据
INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Transaction {
    /**
     * 以转账业务为例说明JDBC中事务的用法
     * 主要是Connection接口中有关于事务的方法
     * 步骤
     *      1.获取链接
     *      2.开启事务
     *      3.获取到PreparedStatement
     *      4.使用PreparedStatement执行两次更新操作
     *      5.正常情况下提交事务
     *      6.出现异常回滚事务
     *      7.最后释放资源
     */
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement ps = null;
        try{
            //注册驱动,获取连接
            connection = JdbcUtils.getConnection();

            //开启事务
            connection.setAutoCommit(false);

            //获取到PreparedStatement,从Jack账户扣钱
            String sql1 = "update account set balance=balance-? where name=?";
            ps = connection.prepareStatement(sql1);
            ps.setInt(1,500);
            ps.setString(2,"Jack");
            ps.executeUpdate();

            //出现异常
            System.out.println(100/0);

            //给rose账户加钱
            String sql2 = "update account set balance=balance+? where name=?";
            ps = connection.prepareStatement(sql2);
            ps.setInt(1,500);
            ps.setString(2,"Rose");
            ps.executeUpdate();

            //提交事务
            connection.commit();
            System.out.println("转账成功");
        }catch (Exception e){
            e.printStackTrace();
            try{
                //事务的回滚
                connection.rollback();
            }catch (SQLException e1){
                e1.printStackTrace();
            }
            System.out.println("转账失败");
        }finally {
            //释放资源
            JdbcUtils.close(connection,ps);
        }
    }
}

五 数据库连接池

1 介绍:

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

好处:

节约资源,用户访问高效

实现

一般我们不去实现它,有数据库厂商来实现

  • C3P0:数据库连接池技术
  • Druid:数据库连接池实现技术,由阿里巴巴提供的 

2 C3P0:数据库连接池技术

步骤:
            1. 导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,
                * 不要忘记导入数据库驱动jar包
            2. 定义配置文件:
                * 名称: c3p0.properties 或者 c3p0-config.xml
                * 路径:直接将文件放在src目录下即可。

            3. 创建核心对象 数据库连接池对象 ComboPooledDataSource
            4. 获取连接: getConnection

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

3 Druid:数据库连接池实现技术

步骤:
            1. 导入jar包 druid-1.0.9.jar
            2. 定义配置文件:
                * 是properties形式的
                * 可以叫任意名称,可以放在任意目录下
            3. 加载配置文件。Properties
            4. 获取数据库连接池对象:通过工厂来来获取  DruidDataSourceFactory
            5. 获取连接:getConnection

//3.加载配置文件
Properties pro = new Properties();
InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//4.获取连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
//5.获取连接
Connection conn = ds.getConnection();

4 定义一个工具类,方便调用

            1. 定义一个类 JDBCUtils
            2. 提供静态代码块加载配置文件,初始化连接池对象
            3. 提供方法
                1. 获取连接方法:通过数据库连接池获取连接
                2. 释放资源
                3. 获取连接池的方法

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import javax.xml.crypto.Data;
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 {

    //定义成员变量DataSource
    private static DataSource ds;
    static {
        try{
            //加载配置文件
            Properties pro = new Properties();
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //获取DataSource
            ds = DruidDataSourceFactory.createDataSource(pro);
        }catch (IOException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

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

    /**
     * 释放资源
     * @param statement
     * @param connection
     */
    public static void close(Statement statement,Connection connection){
        if(statement != null){
            try{
                statement.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if(connection != null){
            try{
                connection.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        close(null,statement,connection);
    }

    /**
     * 释放资源
     * @param resultSet
     * @param statement
     * @param connection
     */
    public static void close(ResultSet resultSet,Statement statement, Connection connection){

        if(resultSet != null){
            try{
                resultSet.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if(statement != null){
            try{
                statement.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if(connection != null){
            try{
                connection.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        close(null,statement,connection);
    }

    /**
     * 获取连接池的方法
     * @return
     */
    public static DataSource getDataSource(){
        return ds;
    }
}

5 Spring JDBC

Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

步骤:

1. 导入jar包
2. 创建JdbcTemplate对象。依赖于数据源DataSource
            * JdbcTemplate template = new JdbcTemplate(ds);

3. 调用JdbcTemplate的方法来完成CRUD的操作

  • update():执行DML语句。增、删、改语句
  • queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合。注意:这个方法查询的结果集长度只能是1
  • queryForList():查询结果将结果集封装为list集合。 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
  • query():查询结果,将结果封装为JavaBean对象。query的参数:RowMapper。一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装。new BeanPropertyRowMapper<类型>(类型.class)
  • queryForObject:查询结果,将结果封装为对象。 一般用于聚合函数的查询

以案例形式说明如何使用

假设数据库中存在一张emp表,其字段如下图

 我们需要创建一个Emp的实体类,用于封装从数据库中取出来的数据

其中需要注意的是,在定义字段使要使用包装类,例如Integer和Double,否则当字段为空的时候会报错

import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

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

public class JdbcTemplateTest {
    /**
     * 使用Spring JDBC中的JDBCTemplate对象简化JDBC的开发
     * 需求
     * 1. 修改1号数据的 salary 为 10000
     * 2. 添加一条记录
     * 3. 删除刚才添加的记录
     * 4. 查询id为1的记录,将其封装为Map集合
     * 5. 查询所有记录,将其封装为List
     * 6. 查询所有记录,将其封装为Emp对象的List集合
     * 7. 查询总记录数
     */

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

    //1.获取JDBCTemplate对象
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    /**
     * 1. 修改1号数据的 salary 为 10000
     */
    @Test
    public void test1(){
        String sql = "update emp set salary=1000 where id=1001";
        int count = template.update(sql);
        System.out.println(count);
    }

    /**
     * 2. 添加一条记录
     */
    @Test
    public void test2(){
        String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";
        int count = template.update(sql,1006,"郭靖",10);
        System.out.println(count);
    }

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

    /**
     * 4.查询id为1001的记录,将其封装为Map集合
     * 注意:这个方法查询的结果集长度只能是1
     */
    @Test
    public void test4(){
        String sql = "select * from emp where id = ?";
        Map<String, Object> map = template.queryForMap(sql, 1001);
        System.out.println(map);
    }

    /**
     * 5. 查询所有记录,将其封装为List
     */
    @Test
    public void test5(){
        String sql = "select * from emp";
        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 emp";
        List<Emp> list = template.query(sql, new RowMapper<Emp>() {
            @Override
            public Emp mapRow(ResultSet resultSet, int i) throws SQLException {
                Emp emp = new Emp();
                int id = resultSet.getInt("id");
                String ename = resultSet.getString("ename");
                int job_id = resultSet.getInt("job_id");
                int mgr = resultSet.getInt("mgr");
                Date joindate = resultSet.getDate("joindate");
                double salary = resultSet.getDouble("salary");
                double bonus = resultSet.getDouble("bonus");
                int dept_id = resultSet.getInt("dept_id");

                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(joindate);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);
                return emp;
            }
        });
        for(Emp emp:list){
            System.out.println(emp);
        }
    }

    /**
     * 7. 查询所有记录,将其封装为Emp对象的List集合
     */
    @Test
    public void test7(){
        String sql = "select * from emp";
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
        for(Emp emp:list){
            System.out.println(emp);
        }
    }

    /**
     * 8. 查询总记录数
     */
    @Test
    public void test8(){
        String sql = "select count(id) from emp";
        Long total = template.queryForObject(sql, Long.class);
        System.out.println(total);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值