Loading

01、JDBC

1、引言

1.1、如何操作数据库

  使用客户端工具访问数据库,需要手工建立连接,输入用户名和密码登录,编写SQL语句,点击执行,查看操作结果(结果集或受影响行数)。

1.2、实际如何操作数据库

  在实际开发中,当用户的数据发生改变时,不可能通过客户端操作执行SQL语句,因为操作量过大,无法保证效率和正确性

2、JDBC (Java Database Connectivity)

2.1、什么是JDBC

  JDBC (Java Database Connectivity) Java连接数据库的规范(标准),可以使用Java 语言连接数据库完成CRUD操作。

2.2、JDBC核心思想

  Java 中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类〈Driver数据库驱动)。

2.2.1、MySQL数据库驱动

  mysql-connector-java-5.1.X适用于5.X版本

  mysql-connector-java-8.0.X适用于8.X版本

jar包下载地址

链接:https://pan.xunlei.com/s/VMezQUzS4jFhrN4LyyniwXwBA1
提取码:nwrw
复制这段内容后打开手机迅雷App,查看更方便

2.2.2、JDBC API

  JDBC是由多个接口和类进行功能实现。

类型 权限定名 简介
class java.sql.DriverManager 管理多个数据库驱动类,提供了获取数据库连接的方法
interface java.sql.Connection 代表一个数据库连接(当connection不是null时,表示已连接数据库)
interface java.sql.Statement 发送SQL语句到数据库工具
interface java.sql.ResultSet 保存SQL查询语句的结果数据(结果集)
class java.sql.SQLException 处理数据库应用程序时所发生的异常

2.3、环境搭建

  创建Java项目

  在项目下新建lib文件夹,用于存放jar文件。

  将mysql 驱动mysql-connector-java-5.1.X复制到项目的lib文件夹中。

  选中lib文件夹右键Add as Libraay,点击OK。

3、JDBC开发步骤【重点】

3.1、注册驱动

使用 Class.forName("com.mysql.jdbc.Driver");手动加载字节码文件到JVM中。

class.forName ( " com.mysql.jdbc. Driver");//加载驱动

3.2、连接数据库

通过 DriverManager.getConnection(url,user,password)获取数据库连接对象

  URL: jdbc:mysql://localhost:3306/mydb2

  username: root

  password: root

Connection conn = DriverManager. getConnection(" jdbc:mysql://localhost:3306/mydb2?useUnicode=true&characterEncoding=utf8", "root", "1234");

URL(Uniform Resource Locator)统一资源定位符:由协议、IP、端口、SID(程序实例名称)组成

测试是否链接数据库是否成功

        Class.forName("com.mysql.jdbc.Driver");
        String url ="jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8";
        String passworld ="root";
        String username = "root";
        Connection connection = DriverManager.getConnection(url,passworld,username);
        if (connection != null){
            System.out.println("连接到数据库啦");
        }else {
            System.out.println("连接失败");
        }

3.3、获取发送SQL的对象

通过 Connection对象获得Statement对象,用于对数据库进行通用访问。

Statement statement =conn.createStatement();

3.4、执行sQL语句

执行SQL语句并接收执行结果。

String sql ="INSERT INTO t_jobs(JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY)VALUES( 'JAVA_Le' ,'JAVA_Lecturer' , 4008,10808) ";
int result = statement.executeUpdate(sql);//执行SQL语句并接收结果

注意:

  在编写DML语句时,一定要注意字符串参数的符号是单引号'值'

  DML语句:增删改时,返回受影响行数(int类型)。

  DQL语句:查询时,返回结果数据(ResultSet结果集)。

测试添加成功后,返回的值

        // 注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 获取连接
        String url ="jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8";
        String passworld ="root";
        String username = "root";
        Connection connection = DriverManager.getConnection(url,passworld,username);
        // 获取发送sql的对象
        Statement statement = connection.createStatement();
        // 执行sql语句
        String sql = "INSERT INTO `t_jobs` (`JOB_ID`,`JOB_TITLE`,`MIN_SALARY`,`MAX_SALARY`) VALUE ('JAVA_Le','JAVA_Lecturer',250,9000)";
        int i = statement.executeUpdate(sql);
        System.out.println("执行的结果" +i);

3.5、处理结果

  接受处理操作结果。

if(result == 1){
  System.out.println( " Success");
}

受影响行数:逻辑判断、方法返回。

查询结果集:迭代、依次获取。

3.6、释放资源

遵循先开后关原则,释放所使用到的资源对象。

statement.close();
conn.close();

3.7、综合案例

  整合以上核心六步,实现向数据库表中插入—条数据。

        // 1、注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 2、获取连接
        String url ="jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8";
        String passworld ="root";
        String username = "root";
        Connection connection = DriverManager.getConnection(url,passworld,username);
        // 3、获取发送sql的对象
        Statement statement = connection.createStatement();
        // 4、执行sql语句
        String sql = "INSERT INTO `t_jobs` (`JOB_ID`,`JOB_TITLE`,`MIN_SALARY`,`MAX_SALARY`) VALUE ('JAVA_Les','JAVA_Lecturer',250,9000)";
        int i = statement.executeUpdate(sql);
        // 5、处理结果
        if (i == 1){
            System.out.println("Success");
        }
        // 6、释放资源
        statement.close();
        connection.close();

4、ResultSet(结果集)

  在执行查询SQL后,存放查询到的结果集数据。

4.1、接收结果集

ResultSet rs = statement.executeQuery(sql);
ResultSet rs= statement. executeQuery( "SELECT * FROM t_employees;" );

4.2、遍历 ResultSet中的数据

ResultSet以表(table)结构进行临时结果的存储,需要通过JDBC API将其中数据进行依次获取。

  数据行指针︰初始位置在第一行数据前,每调用一次boolean next()方法Resultset的指针向下移动一行,结果为true,表示当前行有数据。

  rs.getXxx(整数);代表根据列的编号顺序获得,从1开始

  rs.getXxx(""列名");代表根据列名获得。

  boolean next() throws SQLException //判断rs 结果集中下一行是否存在数据

4.2.1、遍历方法

int getInt(int columnIndex) throws SQLException//获得当前行第N列的int值
int getInt(String columnLabel) throws SQLException//获得当前行columnLabel列的int值
double getDouble(int columnIndex) throws SQLException //获得当前行第N列的double值 double getDouble(String columnLabel) throws SQLException //获得当前行columnLabel列的double值

String getString(int columnIndex) throws SQLException //获得当前行第N列的String值 String getString(String columnLabel) throws SQLException//获得当前行columnLabel列的String值

注意: 列的编号从1开始。

4.3、综合案例

对t_jobs表中的所有数据进行遍历。

4.3.1、根据列的名称获取

        // 加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8";
        String user = "root";
        String password = "root";
        // 获取连接数据库对象
        Connection connection = DriverManager.getConnection(url, user, password);
        // 获取执行sql对象
        Statement statement = connection.createStatement();

        String sql = "SELECT * FROM `t_jobs`";
        //执行sql语句
        ResultSet resultSet = statement.executeQuery(sql);

        // 处理结果集
        while (resultSet.next()){
            String job_id = resultSet.getString("JOB_ID");
            String job_title = resultSet.getString("JOB_TITLE");
            String min_salary = resultSet.getString("MIN_SALARY");
            String max_salary = resultSet.getString("MAX_SALARY");

            System.out.println(job_id+"\t"+job_title+"\t"+min_salary+"\t"+max_salary);
        }

        // 释放资源
        resultSet.close();
        statement.close();
        connection.close();

4.3.2、根据列的编号获取数据

        // 与上相同
        // 处理结果集
        while (resultSet.next()){
            String job_id = resultSet.getString(1);
            String job_title = resultSet.getString(2);
            String min_salary = resultSet.getString(3);
            String max_salary = resultSet.getString(4);

            System.out.println(job_id+"\t"+job_title+"\t"+min_salary+"\t"+max_salary);
        }
        // 释放资源

5、常见错误

  java.lang.ClassNotFoundException: 找不到类(类名书写错误、没有导入jar包)

  java.sqL.SQLException: 与sql语句相关的错误(约束错误、表名列名书写错误)建议:在客户端工具中测试SQL语句之后再粘贴在代码中

  com.mysqL.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 原因:列值Sting类型没有加单引号

  Duplicate entry '1' for key 'PRIMARY' 原因,主键值已存在或混乱,更改主键值或清空表

  com.mysqL.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'password' in 原因: 可能输入的值的类型不对,确定是否插入的元素时对应的值的类型正确

6、综合案例【登录】

6.1、创建表

  创建一张用户表User

    id ,主键、自动增长。

    用户名,字符串类型,唯一、非空。密码,字符串类型,非空

    手机号码,字符串类型

  插入1条测试语句

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(20) UNICODE NOT NULL,
    PASSWORD VARCHAR(20) NOT NULL,
    phone VARCHAR(11)
)CHARSET=utf8

INSERT INTO users (`username`,`password`,`phone`)VALUE ('xiaohe','123456','18211510956')

6.2、实现登录

  通过控制台用户输入用户名和密码。

  用户输入的用户名和密码作为条件,编写查询SQL语句。

  如果该用户存在,提示登录成功,反之提示失败。

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = scanner.nextLine();
        System.out.println("请输入密码");
        String password = scanner.nextLine();

        // 注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8";
        String user = "root";
        String pword = "root";
        // 获取连接数据库对象
        Connection connection = DriverManager.getConnection(url, user, pword);
        // 获取执行sql对象
        Statement statement = connection.createStatement();
        String sql = "SELECT * FROM users WHERE username = '"+username+"' AND PASSWORD = '"+password+"'";
        //执行sql
        ResultSet resultSet = statement.executeQuery(sql);
        // 处理结果集
        if (resultSet.next()){
            System.out.println("登录成功");
        }else {
            System.out.println("登录失败");
        }

        // 关闭资源
        resultSet.close();
        statement.close();
        connection.close();

7、SQL注入问题

7.1、什么是SQL注入

  用户输入的数据中有SQL关键字或语法并且参与了SQL语句的编译,导致SQL语句编译后的条件含义为true,一直得到正确的结果这种现象称为SQL注入。

7.2、如何避免SQL注入

  由于编写的SQL语句是在用户输入数据,整合后再进行编译。所以为了避免SQL注入的问题,我们要使SQL语句在用户输入数据前就已进行编译成完整的 SQL语句,再进行填充数据

8、PreparedStatement【重点】

  PreparedStatement继承了Statement接口,执行SQL语句的方法无异。

8.1、PreparedStatement的应用

  作用:

    预编译SQL语句,效率高。

    安全,避免SQL注入。

    可以动态的填充数据,执行多个同构的SQL语句。

8.1.1、参数标记

//1.预编译SQL 语句
PreparedStatement pstmt = conn.prepareStatement("select ± from user where username=? and password=7");

 

注意:JDBC中的所有参数都由?符号占位,这被称为参数标记。在执行sQL语句之前,必须为每个参数提供值。

8.1.2、动态参数绑定

pstmt.setXxx(下标,值) 参数下标从1开始,为指定参数下标绑定值

//1.预编译SQL语句
PreparedStatement pstmt = conn.prepareStatement("select * from user where username=? and password=7");//2.为参数下标赋值
pstmt.setString(1, username);
pstmt.setString(2, password);

9、封装工具类

  在实际JDBC的使用中,存在着大量的重复代码:例如连接数据库、关闭数据库等这些操作 !

  我们需要把传统的JDBC代码进行重构,抽取出通用的JDBC工具类! 以后连接任何数据库、释放资源都可以使用这个工具类。

 

 

 

9.1、重用性方案

封装获取连接、释放资源两个方法。

  提供public static Connection getConnection()方法。

  提供public static void closeAll(Connection conn , Statement sm , ResultSet rs){}方法。

9.1.1、重用工具类实现

package com.huiruan.JDBC;

import java.sql.*;

public class JDBCUtils {

    // 加载驱动
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 获取连接
    public static Connection getConnection(){
        Connection connection = null;
        try {
            // 获取连接
            String url ="jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8";
            String passworld ="root";
            String username = "root";
            connection = DriverManager.getConnection(url, passworld, username);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    // 关闭连接
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){
        try {
            if (resultSet != null){
                resultSet.close();
            }
            if (statement != null){
                statement.close();
            }
            if (connection != null){
                connection.close();
            }

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

9.2、跨平台方案

定义public static final Properties prop = new Properties();//读取配置文件的Map

定义static{

  // 首次使用工具类时,加载驱动

  InputStream is = JDBCUtil.class.getResourceAsStream("路径");//通过复用本类自带流,读取jdbc.properties配置文件。

  classPath = bin

  prop.load(is); //通过prop对象将流中的配置信息分割成键值对

  String driverName = prop.getProperty("driver");//通过driverName的键获取对应的值(com.mysqL.jdbc.Driver)

  Class.forName(driverName);//加载驱动
}

9.2.1、跨平台工具类实现

  在src目录下新建db.properties文件。

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8
username=root
passworld=root

工具类的封装。

package com.huiruan.JDBC2;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {
    // 存储配置文件的map
   private static final Properties PROPERTIES =  new Properties();

    static {
        InputStream resourceAsStream = JDBCUtils.class.getResourceAsStream("/db.properties");

        try {
            // 通过流,将配置文件内容加载到properties集合
            PROPERTIES.load(resourceAsStream);
            String driver = PROPERTIES.getProperty("driver");
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        Connection connection = null;
        try {
            String url = PROPERTIES.getProperty("url");
            String username = PROPERTIES.getProperty("username");
            String passworld = PROPERTIES.getProperty("passworld");
            connection = DriverManager.getConnection(url, username, passworld);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){

        try {
            if (resultSet != null){
                resultSet.close();
            }

            if (statement != null){
                statement.close();
            }

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

}

10、ORM

ORM(object Relational Mapping)。

从数据库查询到的结果集(ResultSet)在进行遍历时,逐行遍历,取出的都是零散的数据。在实际应用开发中,我们需要将零散的数据进行封装整理。

10.1、实体类(entity):零散数据的载体

一行数据中,多个零散的数据进行整理。

通过entity的规则对表中的数据进行对象的封装。

表名=类名;列名=属性名;提供各个属性的get、set方法。

提供无参构造方法、(视情况添加有参构造)。

10.1.1、ORM应用

  entity实体类

package com.huiruan.JDBC2;

public class T_Jobs {
    private String job_id;
    private String job_title;
    private String min_salary;
    private String max_salary;

    public T_Jobs() {
    }

    public T_Jobs(String job_id, String job_title, String min_salary, String max_salary) {
        this.job_id = job_id;
        this.job_title = job_title;
        this.min_salary = min_salary;
        this.max_salary = max_salary;
    }

    public String getJob_id() {
        return job_id;
    }

    public String getJob_title() {
        return job_title;
    }

    public String getMin_salary() {
        return min_salary;
    }

    public String getMax_salary() {
        return max_salary;
    }

    public void setJob_id(String job_id) {
        this.job_id = job_id;
    }

    public void setJob_title(String job_title) {
        this.job_title = job_title;
    }

    public void setMin_salary(String min_salary) {
        this.min_salary = min_salary;
    }

    public void setMax_salary(String max_salary) {
        this.max_salary = max_salary;
    }

    @Override
    public String toString() {
        return "T_Jobs{" +
                "job_id='" + job_id + '\'' +
                ", job_title='" + job_title + '\'' +
                ", min_salary='" + min_salary + '\'' +
                ", max_salary='" + max_salary + '\'' +
                '}';
    }
}

查询结果封装

package com.huiruan.JDBC2;

import java.sql.*;

public class TestJDBC {
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            connection = JDBCUtils.getConnection();
            String sql = "SELECT * FROM t_jobs";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                String job_id = resultSet.getString("JOB_ID");
                String job_title = resultSet.getString("JOB_TITLE");
                String min_salary = resultSet.getString("MIN_SALARY");
                String max_salary = resultSet.getString("MAX_SALARY");

                T_Jobs t_jobs = new T_Jobs();
                t_jobs.setJob_id(job_id);
                t_jobs.setJob_title(job_title);
                t_jobs.setMin_salary(min_salary);
                t_jobs.setMax_salary(max_salary);

                System.out.println(t_jobs);
            }


        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeAll(connection, preparedStatement,resultSet);
        }
    }
}

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

DAO 实现了业务逻辑与数据库访问相分离。

  对同一张表的所有操作封装在XxxDaolmpl对象中。

  根据增删改查的不同功能实现具体的方法(insert、update、delete、select、selectAll)

 

 

11.1、创建数据库

# 创建—张表Person,有以下列:
CREATE TABLE Person(
    # id: INT,主键,自动增长
    id INT PRIMARY KEY AUTO_INCREMENT,
    # NAME: VARCHAR(20)非空
    NAME VARCHAR(20) NOT NULL,
    # age: int非空
    age INT NOT NULL,
    # bornDate:DATE
    bornDate DATE,
    # email:字符串
    email VARCHAR(20),
    # address:字符串
    address VARCHAR(20)
)CHARSET=utf8;

11.2、封装实体类

  创建entity实体类Person,编写属性私有化,构造方法get/set方法

package com.huiruan.person;

import java.util.Date;

public class Person {
    private int id;
    private String name;
    private int age;
    private Date bornDate;
    private String email;
    private String address;

    public Person() {
    }

    public Person(String name, int age, Date bornDate, String email, String address) {
        this.name = name;
        this.age = age;
        this.bornDate = bornDate;
        this.email = email;
        this.address = address;
    }

    public Person(int id, String name, int age, Date bornDate, String email, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.bornDate = bornDate;
        this.email = email;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public Date getBornDate() {
        return bornDate;
    }

    public String getEmail() {
        return email;
    }

    public String getAddress() {
        return address;
    }

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

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setBornDate(Date bornDate) {
        this.bornDate = bornDate;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", bornDate=" + bornDate +
                ", email='" + email + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

11.3、编写Daolmpl类

  编写Daolmpl类,提供增删改查方法,使用JDBC 开发步骤,完成功能。

package com.huiruan.person;


import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 增、删、改、查单个、查所有
 * 只做数据库访问操作!不参与逻辑判断
 * 数据库一张表的访问的操作复用!
 */
public class PersonDaoImpl {
    // 新增
    public int insert(Person person) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "INSERT INTO `person` (`NAME`,`age`,`bornDate`,`email`,`address`)VALUE(?,?,?,?,?)";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, person.getName());
            preparedStatement.setInt(2, person.getAge());
            preparedStatement.setDate(3, DataUtils.utildateToSqldate(person.getBornDate()));
            preparedStatement.setString(4, person.getEmail());
            preparedStatement.setString(5, person.getAddress());
            int i = preparedStatement.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeAll(connection, preparedStatement, null);
        }
        return 0;
    }

    // 删除
    public int delete(int id) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "DELETE FROM `person` WHERE id = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,id);
            int i = preparedStatement.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.closeAll(connection,preparedStatement,null);
        }
        return 0;
    }

    // 修改
    public int update(Person person) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "UPDATE `person` SET `NAME` = ?,`age`=?,`bornDate`=?,`email`=?,`address`=? WHERE id = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,person.getName());
            preparedStatement.setInt(2,person.getAge());
            preparedStatement.setDate(3,DataUtils.utildateToSqldate(person.getBornDate()));
            preparedStatement.setString(4,person.getEmail());
            preparedStatement.setString(5,person.getAddress());
            preparedStatement.setInt(6,person.getId());
            int i = preparedStatement.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeAll(connection,preparedStatement,null);
        }
        return 0;
    }

    // 查单个
    public Person seleteOne(int id) {

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "SELECT `id`,`NAME`,`age`,`bornDate`,`email`,`address` FROM `person` WHERE `id` = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,id);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()){
                int id1 = resultSet.getInt("id");
                String name = resultSet.getString("NAME");
                int age = resultSet.getInt("age");
                Date bornDate = resultSet.getDate("bornDate");
                String email = resultSet.getString("email");
                String address = resultSet.getString("address");
                Person person = new Person(id1,name,age,bornDate,email,address);
                return  person;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeAll(connection,preparedStatement,resultSet);
        }
        return null;
    }

    // 查所有
    public List<Person> seleteAll() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "SELECT `id`,`NAME`,`age`,`bornDate`,`email`,`address` FROM `person`";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            ArrayList<Person> personArrayList = new ArrayList<>();
            while (resultSet.next()){
                int id1 = resultSet.getInt("id");
                String name = resultSet.getString("NAME");
                int age = resultSet.getInt("age");
                Date bornDate = resultSet.getDate("bornDate");
                String email = resultSet.getString("email");
                String address = resultSet.getString("address");
                Person person = new Person(id1,name,age,bornDate,email,address);
                personArrayList.add(person);
            }
            return personArrayList;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeAll(connection,preparedStatement,resultSet);
        }
        return null;
    }
}
View Code

12、Date工具类

现有问题:

  数据库存储的数据类型为java.sqlL.Date

  而我们Java应用层存储日期类型为java.util.Date

  当我们用Java应用程序插入带有日期的数据到数据库中时,需要进行转换。

12.1、java.util.Date

  Java语言常规应用层面的日期类型,可以通过字符串创建对应的时间对象。

  无法直接通过JDBC插入到数据库。

12.2、java.sql.Date

  不可以通过字符串创建对应的时间对象,只能通过毫秒值创建对象(1970年至今的毫秒值)。

  可以直接通过JDBC插入到数据库。

12.3、SimpleDateFormat

  格式化和解析日期的具体类。允许进行格式化(日期 -> 文本)、解析(文本 → 日期)和规范化。

12.3.1、SimpleDateFormat应用

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MN-dd" );//指定日期格式
    java.util.Date date = sdf.parse(String dateStr); //将字符串解析成日期类型(java.util.Date)
    String dates = sdf.format(date);//将日期格式化成字符串

12.4、封装DateUtils工具类

package com.huiruan.person;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 时间工具
 */
public class DataUtils {



    // 字符串转时间
    public static java.util.Date strToDate(String str) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date parse = simpleDateFormat.parse(str);
            return parse;
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return null;
    }

    // 时间转字符串
    public static String dateToStr(java.util.Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(date);
        return format;
    }

    // 时间转sql时间
    public static java.sql.Date utildateToSqldate(java.util.Date date) {
        return new java.sql.Date(date.getTime());
    }

}
View Code

13、Service业务逻辑层

13.1、什么是业务

  代表用户完成的一个业务功能,可以由一个或多个DAO的调用组成。(软件所提供的一个功能都叫业务)。

13.2、Service开发流程

 

13.2.1、创建表

CREATE TABLE account(
    cardNo VARCHAR(20) PRIMARY KEY,
    PASSWORD VARCHAR(20) NOT NULL,
    NAME VARCHAR(20) NOT NULL,
    balance DOUBLE NOT NULL
)CHARSET=utf8;

INSERT INTO account(`cardNo`,`password`,`name`,`balance`)VALUE('6002','1234','xiaohe',1000);
INSERT INTO account(`cardNo`,`password`,`name`,`balance`)VALUE('6003','1234','xiaoming',100)

13.2.2、实体类

package com.huiruan.account;

public class Account {
    private String cardNo;
    private String password;
    private String name;
    private double balance;

    public Account() {
    }

    public Account(String cardNo, String password, String name, double balance) {
        this.cardNo = cardNo;
        this.password = password;
        this.name = name;
        this.balance = balance;
    }

    public String getCardNo() {
        return cardNo;
    }

    public void setCardNo(String cardNo) {
        this.cardNo = cardNo;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Account{" +
                "cardNo='" + cardNo + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", balance=" + balance +
                '}';
    }
}
View Code

 13.2.3、AccountDaoImpl

package com.huiruan.account;

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

public class AccountDaoImpl {

    // 查询用户
    public Account selectById(String id){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection= JDBCUtils.getConnection();
            String sql = "SELECT * FROM account WHERE cardNo = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,id);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()){
                String cardNo = resultSet.getString("cardNo");
                String password = resultSet.getString("password");
                String name = resultSet.getString("name");
                double balance = resultSet.getDouble("balance");
                Account account = new Account(cardNo, password, name, balance);
                return account;
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeAll(connection,preparedStatement,resultSet);
        }
        return null;
    }

    // 更新用户
    public int UpdateById(Account account){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "UPDATE `account` SET `password`=?,`name`=?,`balance`=? WHERE `cardNo` = ? ";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,account.getPassword());
            preparedStatement.setString(2,account.getName());
            preparedStatement.setDouble(3,account.getBalance());
            preparedStatement.setString(4,account.getCardNo());
            int i = preparedStatement.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeAll(connection,preparedStatement,null);
        }
        return 0;
    }
}
View Code

13.2.4、Service开发流程

13.2.5、AccountServiceImpl

package com.huiruan.account;

public class AccountServiceImpl {
    public String transfer(String fromNo,String pwd,String toNo,double money){
        String result = "转账失败";

        AccountDaoImpl accountDao = new AccountDaoImpl();

        try {
            // 查询fromNo用户是否存在
            Account account = accountDao.selectById(fromNo);
            if (account == null){
                throw new RuntimeException("---- fromNO用户不存在 -----");
            }

            // 验证fromNo的密码是否正确
            if (!account.getPassword().equals(pwd)){
                throw new RuntimeException("-- 密码错误 --");
            }

            // 验证余额是否充足
            if (account.getBalance() < money){
                throw new RuntimeException("-- 余额不足 --");
            }

            // 查询toNo用户是否存在
            Account account1 = accountDao.selectById(toNo);
            if (account1 == null){
                throw new RuntimeException("-- toNo用户不存在 --");
            }

            // 减少fromNo用户余额
            account.setBalance(account.getBalance() - money);
            accountDao.UpdateById(account);

            int i = 10/0;

            // 添加tONo用户余额
            account1.setBalance(account1.getBalance() + money);
            accountDao.UpdateById(account1);

            result = "转账成功";
        } catch (RuntimeException e) {
            e.printStackTrace();

        } finally {
        }


        return result;
    }
}
View Code

14、事务

在JDBC 中,获得 Connection对象开始事务--提交或回滚--关闭连接。其事务策略是

  conn.setAutoCommit(false);//true等价于1,false等价于0

  conn.commit();//手动提交事务

  conn.rollback();//手动回滚事务

14.1、service层控制事务

package com.huiruan.account;

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

public class AccountServiceImpl {
    public String transfer(String fromNo,String pwd,String toNo,double money){
        String result = "转账失败";

        AccountDaoImpl accountDao = new AccountDaoImpl();

        Connection connection = null;

        try {
            // 创建数据库连接
            connection = JDBCUtils.getConnection();

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

            // 查询fromNo用户是否存在
            Account account = accountDao.selectById(fromNo);
            if (account == null){
                throw new RuntimeException("---- fromNO用户不存在 -----");
            }

            // 验证fromNo的密码是否正确
            if (!account.getPassword().equals(pwd)){
                throw new RuntimeException("-- 密码错误 --");
            }

            // 验证余额是否充足
            if (account.getBalance() < money){
                throw new RuntimeException("-- 余额不足 --");
            }

            // 查询toNo用户是否存在
            Account account1 = accountDao.selectById(toNo);
            if (account1 == null){
                throw new RuntimeException("-- toNo用户不存在 --");
            }

            // 减少fromNo用户余额
            account.setBalance(account.getBalance() - money);
            accountDao.UpdateById(account);

            int i = 10/0;

            // 添加tONo用户余额
            account1.setBalance(account1.getBalance() + money);
            accountDao.UpdateById(account1);

            connection.commit();

            result = "转账成功";
        } catch (Exception e) {
            e.printStackTrace();
            try {
                System.out.println("出现异常,回滚");
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            JDBCUtils.closeAll(connection,null,null);
        }


        return result;
    }
}
View Code

  以上代码没有控制到事务

14.2、解决方案

  传递Connection

    为了解决线程中Connection对象不同步的问题,可以将Connection对象通过service传递给各个DAO方法吗?

14.2.1、传递的问题

  如果使用传递Connection,容易造成接口污染(BadSmell)。

  定义接口是为了更容易更换实现,而将Connection定义在接口中,会造成污染当前接口。

14.3、解决方案

  ThreadLocal

    可以将整个线程中(单线程)中,存储一个共享值。

    线程拥有一个类似Map的属性,键值对结构<ThreadLocal对象,值>。

14.4、ThreadLocal应用

  一个线程共享同一个ThreadLocal,在整个流程中任一环节可以存值或取值。

 

14.4.1、参数绑定

  在DBUtils中,将当前 Connection对象添加到ThreadLocal中。

package com.huiruan.account;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {

    private static final Properties PROPERTIES = new Properties();

    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    static {
        try {
            InputStream resourceAsStream = JDBCUtils.class.getResourceAsStream("/db.properties");
            PROPERTIES.load(resourceAsStream);
            Class.forName(PROPERTIES.getProperty("driver"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 获取连接
    public static Connection getConnection() {
        String url = PROPERTIES.getProperty("url");
        String username = PROPERTIES.getProperty("username");
        String passworld = PROPERTIES.getProperty("passworld");
        // 通过threadLocal获取连接
        Connection connection = threadLocal.get();
        try {
            if (connection == null) {
                connection = DriverManager.getConnection(url, username, passworld);
                // 将connection保存到threadLocal中
                threadLocal.set(connection);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    // 开启事务
    public static void begin() {

        try {
            Connection connection = getConnection();
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // 提交事务
    public static void commit() {
        Connection connection = null;
        try {
            connection = getConnection();
            connection.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(connection, null, null);
        }
    }

    // 回滚事务
    public static void rollback() {
        Connection connection = null;
        try {
            connection = getConnection();
            connection.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(connection,null,null);
        }
    }


    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (connection != null) {
                connection.close();
                threadLocal.remove(); // 移除connection
            }

            if (statement != null) {
                statement.close();
            }

            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
View Code

dao的connection不能关闭

package com.huiruan.account;

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

public class AccountDaoImpl {

    // 查询用户
    public Account selectById(String id){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection= JDBCUtils.getConnection();
            String sql = "SELECT * FROM account WHERE cardNo = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,id);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()){
                String cardNo = resultSet.getString("cardNo");
                String password = resultSet.getString("password");
                String name = resultSet.getString("name");
                double balance = resultSet.getDouble("balance");
                Account account = new Account(cardNo, password, name, balance);
                return account;
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeAll(null,preparedStatement,resultSet);
        }
        return null;
    }

    // 更新用户
    public int UpdateById(Account account){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "UPDATE `account` SET `password`=?,`name`=?,`balance`=? WHERE `cardNo` = ? ";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,account.getPassword());
            preparedStatement.setString(2,account.getName());
            preparedStatement.setDouble(3,account.getBalance());
            preparedStatement.setString(4,account.getCardNo());
            int i = preparedStatement.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeAll(null,preparedStatement,null);
        }
        return 0;
    }
}
View Code

service开启事务

package com.huiruan.account;

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

public class AccountServiceImpl {
    public String transfer(String fromNo,String pwd,String toNo,double money){
        String result = "转账失败";

        AccountDaoImpl accountDao = new AccountDaoImpl();


        try {
            JDBCUtils.begin();

            // 查询fromNo用户是否存在
            Account account = accountDao.selectById(fromNo);
            if (account == null){
                throw new RuntimeException("---- fromNO用户不存在 -----");
            }

            // 验证fromNo的密码是否正确
            if (!account.getPassword().equals(pwd)){
                throw new RuntimeException("-- 密码错误 --");
            }

            // 验证余额是否充足
            if (account.getBalance() < money){
                throw new RuntimeException("-- 余额不足 --");
            }

            // 查询toNo用户是否存在
            Account account1 = accountDao.selectById(toNo);
            if (account1 == null){
                throw new RuntimeException("-- toNo用户不存在 --");
            }

            // 减少fromNo用户余额
            account.setBalance(account.getBalance() - money);
            accountDao.UpdateById(account);


            // 添加tONo用户余额
            account1.setBalance(account1.getBalance() + money);
            accountDao.UpdateById(account1);

           JDBCUtils.commit();
            result = "转账成功";
        } catch (Exception e) {
            e.printStackTrace();
            JDBCUtils.rollback();
        }
        return result;
    }
}
View Code

15、三层架构

15.1、什么是三层

  表示层

    命名: XXXView

    职责: 收集用户的数据和需求、展示数据。

  业务逻辑层:

    命名: XxXServicelmpl

    职责: 数据加工处理、调用DAO完成业务实现、控制事务。

  数据访问层:

    命名: XXXDaolmpl

    职责: 向业务层提供数据,将业务层加工后的数据同步到数据库。

15.2、三层架构项目搭建

  utils 存放工具类(DBUtils)

  entity 存放实体类(Person)

  dao 存放DAO接口(PersonDao)

    impl 存放DAO接口实现类(PersonDaolmpl)

  service 存放service接口(PersonService)

    impl 存放service接口实现类(PersonServicelmpl)

  view 存放程序启动类(main)

程序设计时,考虑易修改、易扩展,为Service层和DAO层设计接口,便于未来更换实现类

15.3、项目目录

 

15.4、db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8
username=root
passworld=root
View Code

15.5、DbUtils

package com.huiruan.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class DbUtils {
    private static final Properties PROPERTIES = new Properties();
    private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal<>();
    // 注册驱动
    static {
        try {
            // 加载PersonProject资源
            InputStream resourceAsStream = DbUtils.class.getResourceAsStream("/db.properties");
            PROPERTIES.load(resourceAsStream);
            Class.forName(PROPERTIES.getProperty("driver"));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     *获取连接
     * @return connection
     */
    public static Connection getConnection(){
        // 获取连接 connection
        Connection connection = THREAD_LOCAL.get();
        try {
            if (connection == null){
                connection = DriverManager.getConnection(PROPERTIES.getProperty("url"),PROPERTIES.getProperty("username"),PROPERTIES.getProperty("passworld"));
                THREAD_LOCAL.set(connection);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 关闭连接
     * @param connection
     * @param statement
     * @param resultSet
     */
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){
        try {
            if (connection != null){
                connection.close();
            }

            if (statement != null){
                statement.close();
            }

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

    /**
     * 开启事务
     */
    public static void setAutoCommit(){
        try {
            Connection connection = getConnection();
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 提交事务
     */
    public static void commit(){
        try {
            Connection connection = getConnection();
            connection.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 回滚事务
     */
    public static void rollback(){
        try {
            Connection connection = getConnection();
            connection.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
View Code

15.6、DateUtils

package com.huiruan.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtils {

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    /**
     *  字符串转时间
     * @param str 字符串
     * @return 时间
     */
    public static java.util.Date stringToDate(String str){
        Date parse = null;
        try {
            parse = simpleDateFormat.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;
    }

    /**
     *  时间转字符串
     * @param date 时间
     * @return 字符串
     */
    public static String dateToStr(java.util.Date date){
        return simpleDateFormat.format(date);
    }

    /**
     *  util时间转util时间
     * @param date util时间
     * @return util时间
     */
    public static java.sql.Date utilsdateToSqldate(java.util.Date date){
        return new java.sql.Date(date.getTime());
    }

}
View Code

15.7、DaoUtils

package com.huiruan.utils;

import com.huiruan.advanced.RowMapper;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class DaoUtils<T> {

    /**
     * 公共处理增、删、改的方法
     * @param sql
     * @param args
     * @return
     */
    public int commonsUpdate(String sql,Object... args){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = DbUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i <args.length ; i++) {
                preparedStatement.setObject(i+1,args[i]);
            }
            int i = preparedStatement.executeUpdate();
            return i;

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DbUtils.closeAll(null,preparedStatement,null);
        }
        return 0;
    }

    /**
     * 公共查询方法
     * @param sql
     * @param rowMapper
     * @param args
     * @return
     */
    public List<T> commonsSelect(String sql, RowMapper<T> rowMapper, Object... args){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<T> list = new ArrayList<>();
        try {
            connection = DbUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            if (args != null){
                for (int i = 0; i <args.length ; i++) {
                    preparedStatement.setObject(i+1,args[i]);
                }
            }
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                T t = rowMapper.getRow(resultSet);
                list.add(t);
            }
            return list;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DbUtils.closeAll(null,preparedStatement,resultSet);
        }
        return null;
    }
}
View Code

15.8、RowMapper

package com.huiruan.advanced;

import java.sql.ResultSet;

public interface RowMapper<T> {
    public T getRow(ResultSet resultSet);
}
View Code

15.9、PersonRowMapper

package com.huiruan.advanced.impl;

import com.huiruan.advanced.RowMapper;
import com.huiruan.entity.Person;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;

public class PersonRowMapper implements RowMapper<Person> {
    @Override
    public Person getRow(ResultSet resultSet) {
        Person person = null;
        try {
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            int age = resultSet.getInt("age");
            Date bornDate = resultSet.getDate("bornDate");
            String email = resultSet.getString("email");
            String address = resultSet.getString("address");
            person = new Person(id,name,age,bornDate,email,address);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return person;
    }
}
View Code

15.10、Person

package com.huiruan.entity;

import java.util.Date;

public class Person {

    private Integer id;
    private String name;
    private Integer age;
    private Date bornDate;
    private String email;
    private String address;

    public Person() {
    }

    public Person(Integer id, String name, Integer age, Date bornDate, String email, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.bornDate = bornDate;
        this.email = email;
        this.address = address;
    }

    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 Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getBornDate() {
        return bornDate;
    }

    public void setBornDate(Date bornDate) {
        this.bornDate = bornDate;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", bornDate=" + bornDate +
                ", email='" + email + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
View Code

15.11、PersonDao

package com.huiruan.dao;

import com.huiruan.entity.Person;

import java.util.List;

public interface PersonDao {
    public int insert(Person person);
    public int update(Person person);
    public int delete(int id);
    public Person selectOne(int id);
    public List<Person> selectAll();
}
View Code

15.12、PersonDaoImpl

package com.huiruan.dao.impl;

import com.huiruan.advanced.impl.PersonRowMapper;
import com.huiruan.dao.PersonDao;
import com.huiruan.entity.Person;
import com.huiruan.utils.DaoUtils;
import com.huiruan.utils.DateUtils;
import com.huiruan.utils.DbUtils;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.List;

public class PersonDaoImpl implements PersonDao {

    private static DaoUtils<Person> daoUtils = new DaoUtils();

    @Override
    public int insert(Person person) {
       String sql = "INSERT INTO person (`id`,`NAME`,`age`,`bornDate`,`email`,`address`) VALUE (?,?,?,?,?,?)";
       Object[] obj = {person.getId(),person.getName(),person.getAge(),person.getBornDate(),person.getEmail(),person.getAddress()};
       return daoUtils.commonsUpdate(sql,obj);
    }

    @Override
    public int update(Person person) {
        String sql = "UPDATE person SET `NAME` = ?, `age` = ?, `bornDate` = ?, `email` = ?, `address` = ? WHERE `id` = ?";
        Object[] obj = {person.getName(),person.getAge(),DateUtils.utilsdateToSqldate(person.getBornDate()),person.getEmail(),person.getAddress(),person.getId()};
        return daoUtils.commonsUpdate(sql,obj);
    }

    @Override
    public int delete(int id) {
        String sql = "delete from person where id = ?";
        return daoUtils.commonsUpdate(sql, id);
    }

    @Override
    public Person selectOne(int id) {
        String sql = "select * from person where id = ?";
        List<Person> people = daoUtils.commonsSelect(sql,new PersonRowMapper(),id);
        if (!people.isEmpty()){
            return people.get(0);
        }
        return null;
    }

    @Override
    public List<Person> selectAll() {
        String sql = "select * from person";
        List<Person> people = daoUtils.commonsSelect(sql, new PersonRowMapper());
        return people;
    }
}
View Code

16、Druid连接池

   在程序初始化时,预先创建指定数量的数据库连接对象存储在池中。当需要连接数据库时,从连接池中取出现有连接;使用完毕后,也不会进行关闭,而是放回池中,实现复用,节省资源。

16.1 Druid连接池使用步骤

  创建database.properties配置文件。

  引入druid-1.1.5.jar文件。

  引入mysql-connector-java-5.1.25-bin.jar文件。

  引入commons-dbutils-1.7.jar文件。

16.1.1、database.properties配置文件

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8
username=root
password=root
#<!--初始化连接-->
initialSize =10
#最大连接数量
maxActive=20
#<!--最小空闲连接-->
minIdle=5
#<!--超时等待时间以毫秒为单位60000毫秒/1000等于60秒-->
maxWait=5000
View Code

16.1.2、连接池工具类

package com.huiruan.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class DbUtils {
    // 声明连接池对象
    private static  DruidDataSource druidDataSource;

    static {
        // 实例化配置对象
        try {
            Properties properties = new Properties();
            InputStream resourceAsStream = DbUtils.class.getResourceAsStream("/db.properties");
            properties.load(resourceAsStream);
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            druidDataSource = (DruidDataSource) dataSource;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return
     */
    public static Connection getConnection(){
        try {
            return druidDataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  null;
    }

    /**
     * 获取连接池
     * @return
     */
    public static DruidDataSource getDruidDataSource(){
        return druidDataSource;
    }
}
View Code

17、Apache的DbUtils使用

  Commons Dbutils,是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能勾简化JDBC应用程序的开发!同时,不会影响程序的性能。

17.1、DbUtils简介

DbUtils是Java编程中数据库操作实用小工具,小巧、简单、实用

  对于数据表的查询操作,可以把结果转换为List、Array、Set等集合。便于操作。

  对于数据表的DML操作,也变得很简单(只需要写SQL语句)。

17.1.1、DbUtils主要包含

ResultSetHandler接口:转换类型接口

  BeanHandler类:实现类,把一条记录转换成对象

  BeanListHandler类:实现类,把多条记录转换成List集合。

  ScalarHandler类:实现类,适合获取一行一列的数据。

QueryRunner:执行sql语句的类

  增、删、改:update();

  查询:query();

 17.2、DbUtils的使用步骤

导入jar包

  mysql连接驱动jar包

  druid-1.1.5.jar

  database.properties配置文件

  commons-dbutils-1.6.jar

17.2.1、db.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb2?userUnicade=true&characterEncoding=utf8
username=root
password=root
#<!--初始化连接-->
initialSize =10
#最大连接数量
maxActive=20
#<!--最小空闲连接-->
minIdle=5
#<!--超时等待时间以毫秒为单位60000毫秒/1000等于60秒-->
maxWait=5000
View Code

17.2.2、DbUtils工具类

package com.huiruan.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class DbUtils {
    // 声明连接池对象
    private static  DruidDataSource druidDataSource;

    static {
        // 实例化配置对象
        try {
            Properties properties = new Properties();
            InputStream resourceAsStream = DbUtils.class.getResourceAsStream("/db.properties");
            properties.load(resourceAsStream);
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            druidDataSource = (DruidDataSource) dataSource;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return
     */
    public static Connection getConnection(){
        try {
            return druidDataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  null;
    }

    /**
     * 获取连接池
     * @return
     */
    public static DruidDataSource getDruidDataSource(){
        return druidDataSource;
    }
}
View Code

17.2.3、User

package com.huiruan.entity;

public class User {
    private Integer  userId;
    private String  username;
    private String  password;
    private String  address;
    private String  phone;

    public User() {
    }

    public User(Integer userId, String username, String password, String address, String phone) {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.address = address;
        this.phone = phone;
    }

    public User(String username, String password, String address, String phone) {
        this.username = username;
        this.password = password;
        this.address = address;
        this.phone = phone;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getPhone() {
        return phone;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", address='" + address + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }
}
View Code

17.2.4、UserDao

package com.huiruan.dao;

import com.huiruan.entity.User;

import java.util.List;

public interface UserDao {
    public int insert(User user);
    public int update(User user);
    public int delete(int id);
    public User seleteOne(int id);
    public List<User> seleteAll();
}
View Code

17.2.5、UserDaoImpl

package com.huiruan.dao.impl;

import com.huiruan.dao.UserDao;
import com.huiruan.entity.User;
import com.huiruan.utils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.List;

public class UserDaoImpl implements UserDao {

    private QueryRunner queryRunner = new QueryRunner(DbUtils.getDruidDataSource());


    @Override
    public int insert(User user) {
        try {
            String sql = "INSERT INTO `user` (`username`,`password`,`address`,`phone`) VALUE (?,?,?,?)";
            Object[] params = {user.getUsername(),user.getPassword(),user.getAddress(),user.getPhone()};
            return queryRunner.update(sql,params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public int update(User user) {
        try {
            String sql = "UPDATE `user` SET `username` = ?, `password`= ?, `address`= ?, `phone`= ? WHERE `userId` = ?";
            Object[] params = {user.getUsername(),user.getPassword(),user.getAddress(),user.getPhone(),user.getUserId()};
            return queryRunner.update(sql,params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public int delete(int id) {
        try {
            String sql = "DELETE FROM `user` WHERE `userId` = ?";
            return queryRunner.update(sql,id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public User seleteOne(int id) {
        try {
            String sql = "SELECT * FROM `user` WHERE `userId` = ?";
            return queryRunner.query(sql,new BeanHandler<User>(User.class),id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<User> seleteAll() {
        try {
            String sql = "SELECT * FROM `user`";
           return queryRunner.query(sql,new BeanListHandler<User>(User.class));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
View Code

 

posted @ 2021-07-20 23:09  菜鸟的道路  阅读(99)  评论(0)    收藏  举报