JDBC基础知识点(mysql版)参考千锋资料

什么是JDBC

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

JDBC的核心思想

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

在这里插入图片描述

在这里插入图片描述

JDBC开发步骤

我的mysql版本是8.0.20版本的和5.7以前的连接有点区别

DML

1.注册驱动

加载驱动
加载驱动类到内存中,用于访问数据库

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

Class.forName("com.mysql.cj.jdbc.Driver");//加载驱动 5.7以后要加cj


SQLServer: 
com.microsoft.sqlserver.jdbc.SQLServerDriver

MySQL:
com.mysql.jdbc.Driver	(5.7版本以下)
com.mysql.cj.jdbc.Driver  (5.7以上)

2.连接数据库 建立连接

获得连接

Connection DriverManager.getConnection(URL,用户,密码)
通过DriverManager.getConnection(url,user,password) 获取数据库连接对象

URL: jdbc:mysql://localhost:3306/数据库名称?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
username : root
password: 123456

SQLServer:
jdbc:sqlserver://数据库主机名:1433;DatabaseName=数据库名

MySQL:
jdbc:mysql://数据库主机名:3306/数据库名?serverTimezone=UTC 5.7以后
jdbc:mysql://数据库主机名:3306/数据库名     5.7以前

useUnicode=true&characterEncoding=utf8是为了防止中文乱码的

3.获取发送sql的对象

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

Statement statement=conn.createStatement();

4.执行SQL 语句

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

int i = statement.executeUpdate("INSERT INTO bank(id,money) VALUES(4,2000)");

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

DML语句增删改时,返回受影响的行数(int类型)
DQL语句:查询时,返回结果数据(ResultSet结果集)

5.处理结果

          if(i>0){
    
    
                  System.out.println("添加成功");
              }
              else{
    
    
                  System.out.println("添加失败");
              }

DML:返回的是受影响的行数:逻辑判断,方法返回
DQL:返回的是查询结果集:迭代,以此获取

6.释放资源

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

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

综合DML语句

package JDBC;

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

public class jdbc02 {
    
    
    public static void main(String[] args) {
    
    
        Connection conn=null;
        Statement statement=null;
        try {
    
    
            //注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //获得连接对象
              conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?serverTimezone=UTC","root","123456");
             //获得执行sql对象
              statement = conn.createStatement();
              //执行sql语句,并接受结果
             int i = statement.executeUpdate("INSERT INTO bank(id,money) VALUES(4,2000)");
              //处理结果
             if(i>0){
    
    
                  System.out.println("添加成功");
              }
              else{
    
    
                  System.out.println("添加失败");
              }
        } catch (ClassNotFoundException | SQLException e) {
    
    
            e.printStackTrace();
        }
        finally {
    
    
            try {
    
    
                //释放资源
                statement.close();
                conn.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }

        }

    }
}

DQL

 ResultSet rs = statement.executeQuery(sql);
 
 rs = st.executeQuery("select * from  bank");

遍历ResultSet中的数据

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

数据行指针: 初始位置在第一行数据前,每调用依次boolean next()方法 ResultSet的指针向下移动一行,结果为true表示当前行有数据。
rs.getXxx(整数) 代表根据列的编号顺序获得,从1开始
rs.getXxx(列名) 代表根据列名获得

遍历结果集

 while(rs.next()){
    
    
                 int id = rs.getInt("id");
                 int money = rs.getInt("money");
                 System.out.println("id:"+id+"\tmoney:"+money);
             }

注意:列的编号从1开始

DQL综合

package JDBC;

import java.sql.*;

public class jdbc03 {
    
    
    public static void main(String[] args) {
    
    
        Connection conn=null;
        Statement st=null;
        ResultSet rs=null;
        try {
    
    
             //注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //获得连接对象
            conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?serverTimezone=UTC","root","123456");
              st = conn.createStatement();
              //执行sql语句,并接受结果
              rs = st.executeQuery("select * from  bank");
           // 遍历结果集
             while(rs.next()){
    
    
                 int id = rs.getInt("id");
                 int money = rs.getInt("money");
                 System.out.println("id:"+id+"\tmoney:"+money);
             }
        } catch (ClassNotFoundException | SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            try {
    
    
            // 关闭资源
                rs.close();
                st.close();
                conn.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }

        }
    }
}

常见的错误

在这里插入图片描述

SQL注入问题

CREATE TABLE login(

    username VARCHAR(20) UNIQUE NOT NULL,
    PASSWORD VARCHAR(20) NOT NULL


)
INSERT INTO login(username,PASSWORD) VALUES('zhangsan','1234')


SELECT * FROM login WHERE username='zhangsan' AND PASSWORD='1234'
package JDBC;

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

public class jdbc04 {
    
    
    public static void main(String[] args) {
    
    
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入用户名");
        String username=sc.next();
        System.out.println("请输入密码");
        String password=sc.next();
        Connection conn=null;
        Statement st=null;
        ResultSet rs=null;
        try {
    
    
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?serverTimezone=UTC", "root", "123456");
             st= conn.createStatement();
             rs= st.executeQuery("SELECT * FROM login WHERE username='"+username+"' AND PASSWORD='"+password+"'");
             if (rs.next()){
    
    
                 System.out.println("登录成功");
             }
             else{
    
    
                 System.out.println("登录失败");
             }
        } catch (ClassNotFoundException | SQLException e) {
    
    
            e.printStackTrace();
        }
        finally {
    
    
            try {
    
    
                rs.close();
                st.close();
                conn.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }

        }
    }
}

当密码是 abc’ or 1=1;#的时候无论密码输什么都能登录成功

为了解决sql注入问题所以我们要采用PreparedStatement

PreparedStatement作用

预编译SQL语句,效率高
安全,避免SQL注入
可以动态的填充数据,执行多个同构的sql语句

参数标记

预编译SQL语句
pst = conn.prepareStatement("select * from login where username=? and password=?");

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

动态参数绑定

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

//预编译sql语句
             pst = conn.prepareStatement("select * from login where username=? and password=?");
             pst.setString(1,"zhangsan");
             pst.setString(2,"1234");
`Connection`接口:与特定数据库的连接(会话)`PreparedStatement`接口:表示预编译的 SQL 语句的对象。SQL 语句被预编译并存储在 `PreparedStatement` 
对象中。然后可以使用此对象多次高效地执行该语句。

`ResultSet`接口:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
`ResultSet` 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。
`next` 方法将光标移动到下一行;因为该方法在 `ResultSet` 对象没有下一行时
返回 `false`,所以可以在 `while` 循环中使用它来迭代结果集。

Statement与PreparedStatement的区别

1. PreparedStatement是预编译的,对于多次执行的SQL可以大大提高效率。而Statement不行

2. PreparedStatement可以通过占位符的方式解决SQL注入的问题,而Statement不行

3. 二者SQL的传入位置不同

封装工具类

在这里插入图片描述
重用工具类实现
封装获取连接,释放资源两个方法

提供 public static Connection getconnection(){} 方法
提供 public static void closeall(Connection conn,Statement stm ResultSet rs)

package JDBC;

import java.sql.*;

public class DBUtils {
    
    

    static {
    
     //静态代码块,类加载时加载只加载一次
        try {
    
    
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
    }
    //获取连接
    public  static Connection getconnection(){
    
    
        Connection conn=null;
        try {
    
    
            conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?serverTimezone=UTC","root","123456");

        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }
       return conn;
    }

    //释放资源
    public  static  void closeall(Connection conn, PreparedStatement pst, ResultSet rs){
    
    

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

跨平台工具类的实现

在src目录下创建db.properties配置文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db3?serverTimezone=UTC
username=root
password=123456

以后可以直接修改配置文件而不需要修改其他地方

package JDBC;

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

public class DButil {
    
    
    //存储配置文件的map
    private static final Properties PROPERTIES=new Properties();
    //静态代码块仅在类加载的时候加载且仅加载一次
    static {
    
    
        //通过类的方法获得流
        InputStream is = DButil.class.getResourceAsStream("/db.properties");
        try {
    
    
      //通过流将配置文件加载到properties集合中
            PROPERTIES.load(is);
            Class.forName(PROPERTIES.getProperty("driver"));
        } catch (IOException | ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
    }

    public static Connection getconnection(){
    
    
        Connection conn=null;
        try {
    
    
            conn=DriverManager.getConnection(PROPERTIES.getProperty("url"),PROPERTIES.getProperty("username"),PROPERTIES.getProperty("password"));
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }

        return conn;
    }

    public static  void closeall(Connection conn, PreparedStatement pst, ResultSet rs){
    
    
        if(rs!=null){
    
    
            try {
    
    
                rs.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }
        }
        if(pst!=null){
    
    
            try {
    
    
                pst.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }
        }
        if(conn!=null){
    
    
            try {
    
    
                conn.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }
        }

    }
}

ORM

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

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

一行数据中,多个零散的数据进行整理
通过entity的规则对表中的数据进行对象封装
表名=类名  
列名=属性名
提供各个属性的get set 方法
提供无参构造方法(视情况添加有残构造方法)

ORM应用

user实体类

package JDBC;

public class userentity {
    
    
    private String username;
    private  String password;

    public userentity() {
    
    
    }

    public userentity(String username, String password) {
    
    
        this.username = username;
        this.password = password;
    }

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

    @Override
    public String toString() {
    
    
        return "userentity{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

package JDBC;

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 userTest {
    
    
    public static void main(String[] args) {
    
    
        Connection conn=null;
        PreparedStatement pst=null;
        ResultSet rs=null;
        List<userentity> list=new ArrayList();
        try {
    
    
            Class.forName("com.mysql.cj.jdbc.Driver");

            conn=DButil.getconnection();
            pst = conn.prepareStatement("select * from login");
             rs = pst.executeQuery();
             while (rs.next()){
    
    
                 String username = rs.getString("username");
                String password = rs.getString("password");
                  userentity user = new userentity(username, password);
                  list.add(user);
             }
        } catch (ClassNotFoundException | SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            DBUtils.closeall(conn,pst,rs);
        }



         for (userentity u:list){
    
    
             System.out.println(u);
         }
    }
}

DAO

DAO数据访问对象
DAO实现了业务逻辑与数据库相分离
对同一张表所有操作封装在XxxDaoImpl对象中
根据增删改查的不同功能实现具体的方法(insert update delete select selectall)

数据库

首先创建一张表Person

CREATE TABLE person
(

  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(20) NOT NULL,
  age INT NOT NULL,
  borndate DATE,
  emall VARCHAR(20),
  address VARCHAR(20)
)

封装实体类

package Dao;

import java.util.Date;

public class personentity {
    
    
package Dao;

import java.util.Date;

public class personentity {
    
    
    private  int id;
    private  String name;
    private  int age;
    private Date borndate;
    private  String email;
    private  String address;

    public personentity() {
    
    
    }

    public personentity(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 personentity(int id, String name, int age, Date borndate, String emall, 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 void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

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

    public Date getBorndate() {
    
    
        return borndate;
    }

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

    public String getEmail() {
    
    
        return email;
    }

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

    public String getAddress() {
    
    
        return address;
    }

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

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

}

Date 工具类

数据库存储的类型为java.sql.Date 而我们java应用层存储日期类型为java.util.Date,当我们java应用程序插入带有日期的数据到数据库中时需要转换

java.util.Date
java语言常规应用层面的日期类型,可以通过字符串创建对应的时间对象
无法直接通过JDBC插入到数据库

java.sql.Date
不可以通过字符串创建对应的时间对象,只能通过毫秒值创建对象
可以直接通过JDBC插入到数据库

 SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//指定日期格式
         String s="2020-10-10 08:08:08";
        try {
    
    
            Date date = sdf.parse(s);//将字符串解析成日期类型
            System.out.println(date);
        } catch (ParseException e) {
    
    
            e.printStackTrace();
        }
         String s1 = sdf.format(new Date());//将日期格式化字符串
        System.out.println(s1);

Date工具类封装

package Dao;

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

public class Dateutils {
    
    

    public  static final SimpleDateFormat sdf=new SimpleDateFormat("yy-MM-dd");

    public static java.util.Date strtoutildate(String str){
    
    

        try {
    
    
            Date date = sdf.parse(str);
            return date;
        } catch (ParseException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }

    public static  java.sql.Date utiltosqldate(java.util.Date date){
    
    



        return new java.sql.Date(date.getTime());
    }

    public static String utildatetostr(java.util.Date date){
    
    

         String format = sdf.format(date);

          return format;
    }
}

编写DaoImpl类

提供增删改查方法完善jdbc开发步骤,完善功能

package Dao;

import JDBC.DBUtils;

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

public class personDaoImpl {
    
    
    public int insert(personentity person){
    
    
        int count=0;
        Connection conn=null;
        PreparedStatement pst=null;
       conn = DButils.getconnection();
       String sql="insert into person(name,age,borndate,email,address) values(?,?,?,?,?);";
        try {
    
    

            pst = conn.prepareStatement(sql);
            pst.setString(1,person.getName());
            pst.setInt(2,person.getAge());
            pst.setDate(3,Dateutils.utiltosqldate(person.getBorndate()));
            pst.setString(4,person.getEmail());
            pst.setString(5,person.getAddress());
            count = pst.executeUpdate();
            return count;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DButils.closeall(conn,pst,null);
        }

        return 0;
    }

    public int update(personentity person) {
    
    
         Connection conn=null;
         PreparedStatement pst=null;
           int count=0;
         conn= DBUtils.getconnection();
         String sql="update person set name=?,age=?,borndate=?,email=?,address=? where id=?";
        try {
    
    
            pst = conn.prepareStatement(sql);
            pst.setString(1,person.getName());
            pst.setInt(2,person.getAge());
            pst.setDate(3,Dateutils.utiltosqldate(person.getBorndate()));
            pst.setString(4,person.getEmail());
            pst.setString(5,person.getAddress());
            pst.setInt(6,person.getId());
            count= pst.executeUpdate();
            return count;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
             DBUtils.closeall(conn,pst,null);
        }


        return 0;
    }

    public int delete(int id){
    
    
        Connection conn=null;
        PreparedStatement pst=null;
        int count=0;
        String sql="delete from person where id=?;";
        conn=DBUtils.getconnection();
        try {
    
    
            pst = conn.prepareStatement(sql);
            pst.setInt(1,id);
            count = pst.executeUpdate();
            return count;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DBUtils.closeall(conn,pst,null);
        }


        return 0;
    }
    public personentity select(int id){
    
    
        personentity person=null;

        Connection conn=null;
        PreparedStatement pst=null;
        ResultSet rs=null;

        String sql="select * from person where id=?;";
        try {
    
    
            conn=DBUtils.getconnection();
            pst= conn.prepareStatement(sql);
            pst.setInt(1,id);
           rs= pst.executeQuery();
           if(rs.next()){
    
    
               int id1 = rs.getInt("id");
                String name = rs.getString("name");
               int age = rs.getInt("age");
                Date borndate = rs.getDate("borndate");
                String email = rs.getString("email");
                String address = rs.getString("address");
              person = new personentity(id1, name, age, borndate, email, address);
              return  person;

           }
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DBUtils.closeall(conn,pst,rs);
        }


        return person;
    }

    public List<personentity> selectall(){
    
    
        List<personentity> personentities = new ArrayList<>();
         Connection conn=null;
         PreparedStatement pst=null;
         ResultSet rs=null;
         String sql="select * from person";

        try {
    
    
            conn=DBUtils.getconnection();
            pst= conn.prepareStatement(sql);
            rs=pst.executeQuery();
            while (rs.next()){
    
    
                int id1 = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                Date borndate = rs.getDate("borndate");
                String email = rs.getString("email");
                String address = rs.getString("address");
               personentity person = new personentity(id1, name, age, borndate, email, address);
                personentities.add(person);

            }
            return personentities;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DBUtils.closeall(conn,pst,rs);
        }

        return  personentities;
    }
}

service业务逻辑层

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

编写service实现转账功能

事务

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

 conn.setAutoCommit(false); //true等价于1,false等价于0
 conn.commit();//手动提交事务
 conn.rollback();//手动回滚事务

转账业务

account实体类

package account;

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

    public Account() {
    
    

    }

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

    public String getCardID() {
    
    
        return cardID;
    }

    public void setCardID(String cardID) {
    
    
        this.cardID = cardID;
    }

    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{" +
                "cardID='" + cardID + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", balance=" + balance +
                '}';
    }
}

AccountDaoImpl类

package account;

import JDBC.DBUtils;

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

public class AccountDaoImpl {
    
    
    public int insert(Account account){
    
    
        return 0;
    }
    public int  delete(String cardID){
    
    

        return 0;
    }
    public int update(Account account){
    
    
        int count;
        Connection conn=null;
        PreparedStatement pst=null;
        conn=DBUtils.getconnection();
        String sql="update account set password=?,name=?,balance=? where cardID=?";
        try {
    
    
            pst=conn.prepareStatement(sql);
            pst.setString(1,account.getPassword());
            pst.setString(2,account.getName());
            pst.setDouble(3,account.getBalance());
            pst.setString(4,account.getCardID());
            count=pst.executeUpdate();
            return count;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DBUtils.closeall(conn,pst,null);
        }

        return 0;
    }
    public Account select(String cardID){
    
    
        Connection conn=null;
        PreparedStatement pst=null;
        ResultSet rs=null;
        Account account=null;
       conn= DBUtils.getconnection();
       String sql="select * from account where cardID=?";
        try {
    
    
            pst=conn.prepareStatement(sql);
            pst.setString(1,cardID);
             rs = pst.executeQuery();
             if(rs.next()){
    
    
                  String id = rs.getString("cardID");
                  String password = rs.getString("password");
                  String name = rs.getString("name");
                  double balance = rs.getDouble("balance");
                 account=new Account(id,password,name,balance);

             }
             return account;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DBUtils.closeall(conn,pst,rs);
        }
        return  null;
    }
}

AccountserviceImpl 类

package account;

import JDBC.DBUtils;

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

public class AccountserviceImpl {
    
    
    public void transfer(String fromID,String password,String toID,double money) throws SQLException {
    
    
         //1.接收传递参数 转账的卡号 密码 被转的卡号 转账的金额
         //2.组织完善业务功能
        AccountDaoImpl accountDao = new AccountDaoImpl();
        Connection conn=null;
        try {
    
    
            //建立一个数据库连接
            conn= DBUtils.getconnection();
            //开启事务 并且关闭事务的自动提交
            conn.setAutoCommit(false);
            //2.1验证fromID是否存在
            Account account = accountDao.select(fromID);
            if(account==null){
    
    
                throw new RuntimeException("卡号不存在");
            }
            //2.2验证password是否正确
            if(!(password.equals(account.getPassword()))){
    
    
                throw new RuntimeException("密码错误");
            }
            //2.3验证余额是否充足
            if(account.getBalance()<money){
    
    
                throw new RuntimeException("余额不足");
            }
            //2.4验证toID是否存在
            Account account1 = accountDao.select(toID);
            if(account1==null){
    
    
                throw new RuntimeException("对方卡不存在");
            }

            //2.4减少fromID的余额
            account.setBalance(account.getBalance()-money);
            accountDao.update(account);


            //2.5增加toID的余额
            account1.setBalance(account1.getBalance()+money);
            accountDao.update(account1);
            System.out.println("转账成功");
            conn.commit();//手动提交事务
        }catch (RuntimeException | SQLException e){
    
    
            System.out.println("转账失败");
            //出现异常回滚事务
            conn.rollback();//手动回滚事务
            e.printStackTrace();
        }

    }

}

结果发现加了事务结果还是出问题,原因在于connection不唯一,服务层调用了多个connection

解决方法

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

传递的问题

如果使用传递connection容易造成接口污染(badsmell)
定义接口是为了更容易更换实现 而将connection定义在接口中,会造成污染当前接口

解决方法 threadlocal

可以将整个线程中(单线程),存储一个共享值
线程用于一个类似Map的属性,键值对结构为<threadlocal,值>

ThreadLocal

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

在这里插入图片描述

修改后的DButils

package account;


import JDBC.DBUtils;

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 {
    
    
         InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
         try {
    
    
             PROPERTIES.load(is);
             Class.forName(PROPERTIES.getProperty("driver"));
         } catch (IOException | ClassNotFoundException e) {
    
    
             e.printStackTrace();
         }

     }

     public  static Connection getconnection(){
    
    
           Connection conn=THREAD_LOCAL.get();//获取线程中存储的connection对象

         try {
    
    
             if(conn==null){
    
    //如果连接对象为空则创建连接
                 conn= DriverManager.getConnection(PROPERTIES.getProperty("url"),PROPERTIES.getProperty("username"),PROPERTIES.getProperty("password"));
                 THREAD_LOCAL.set(conn);//把连接存在当前线程共享中
             }

            return conn;
         } catch (SQLException throwables) {
    
    
             throwables.printStackTrace();
         }
         return  null;
     }

    public static void closeall(Connection conn, PreparedStatement pst, ResultSet rs){
    
    
        if(rs!=null){
    
    
            try {
    
    
                rs.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }
        }

        if(pst!=null){
    
    
            try {
    
    
                pst.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }
        }

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

    }
}

所以对Dao层里面的关闭连接也要做对应的修改,Service层操作的connection对象应该是同一个,所以在Dao层不应该关闭connection对象,而应该在Service层事务处理完后在关闭connection连接

AccountDaoImpl类

package account;

import JDBC.DBUtils;

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

public class AccountDaoImpl {
    
    
    public int insert(Account account){
    
    
        return 0;
    }
    public int  delete(String cardID){
    
    

        return 0;
    }
    public int update(Account account){
    
    
        int count;
        Connection conn=null;
        PreparedStatement pst=null;
        conn=DBUtils.getconnection();
        String sql="update account set password=?,name=?,balance=? where cardID=?";
        try {
    
    
            pst=conn.prepareStatement(sql);
            pst.setString(1,account.getPassword());
            pst.setString(2,account.getName());
            pst.setDouble(3,account.getBalance());
            pst.setString(4,account.getCardID());
            count=pst.executeUpdate();
            return count;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DBUtils.closeall(null,pst,null);
        }

        return 0;
    }
    public Account select(String cardID){
    
    
        Connection conn=null;
        PreparedStatement pst=null;
        ResultSet rs=null;
        Account account=null;
       conn= DBUtils.getconnection();
       String sql="select * from account where cardID=?";
        try {
    
    
            pst=conn.prepareStatement(sql);
            pst.setString(1,cardID);
             rs = pst.executeQuery();
             if(rs.next()){
    
    
                  String id = rs.getString("cardID");
                  String password = rs.getString("password");
                  String name = rs.getString("name");
                  double balance = rs.getDouble("balance");
                 account=new Account(id,password,name,balance);

             }
             return account;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DBUtils.closeall(null,pst,rs);
        }
        return  null;
    }
}

AccountserviceImpl 类

package account;

import JDBC.DBUtils;

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

public class AccountserviceImpl {
    
    
    public void transfer(String fromID,String password,String toID,double money) throws SQLException {
    
    
         //1.接收传递参数 转账的卡号 密码 被转的卡号 转账的金额
         //2.组织完善业务功能
        AccountDaoImpl accountDao = new AccountDaoImpl();
        Connection conn=null;
        try {
    
    
            //建立一个数据库连接
            conn= DBUtils.getconnection();
            //开启事务 并且关闭事务的自动提交
            conn.setAutoCommit(false);
            //2.1验证fromID是否存在
            Account account = accountDao.select(fromID);
            if(account==null){
    
    
                throw new RuntimeException("卡号不存在");
            }
            //2.2验证password是否正确
            if(!(password.equals(account.getPassword()))){
    
    
                throw new RuntimeException("密码错误");
            }
            //2.3验证余额是否充足
            if(account.getBalance()<money){
    
    
                throw new RuntimeException("余额不足");
            }
            //2.4验证toID是否存在
            Account account1 = accountDao.select(toID);
            if(account1==null){
    
    
                throw new RuntimeException("对方卡不存在");
            }

            //2.4减少fromID的余额
            account.setBalance(account.getBalance()-money);
            accountDao.update(account);


            //2.5增加toID的余额
            account1.setBalance(account1.getBalance()+money);
            accountDao.update(account1);
            System.out.println("转账成功");
            conn.commit();//手动提交事务
        }catch (RuntimeException | SQLException e){
    
    
            System.out.println("转账失败");
            //出现异常回滚事务
            conn.rollback();//手动回滚事务
            e.printStackTrace();
        }finally {
    
    
            DBUtils.closeall(conn,null,null);
        }

    }

}

对事务封装的DBUtils

package account;


import JDBC.DBUtils;

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 {
    
    
         InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
         try {
    
    
             PROPERTIES.load(is);
             Class.forName(PROPERTIES.getProperty("driver"));
         } catch (IOException | ClassNotFoundException e) {
    
    
             e.printStackTrace();
         }

     }

     public  static Connection getconnection(){
    
    
           Connection conn=THREAD_LOCAL.get();//获取线程中存储的connection对象

         try {
    
    
             if(conn==null){
    
    //如果连接对象为空则创建连接
                 conn= DriverManager.getConnection(PROPERTIES.getProperty("url"),PROPERTIES.getProperty("username"),PROPERTIES.getProperty("password"));
                 THREAD_LOCAL.set(conn);//把连接存在当前线程共享中
             }

            return conn;
         } catch (SQLException throwables) {
    
    
             throwables.printStackTrace();
         }
         return  null;
     }
    //事务的开启
     public static void begin()
     {
    
    
        Connection conn=null;
        try {
    
    
            conn=getconnection();
            conn.setAutoCommit(false);
        }catch (SQLException e)
        {
    
    
            e.printStackTrace();
        }

     }
     //提交事务
      public static void commit()
      {
    
    
          Connection conn=null;
          try {
    
    
              conn=getconnection();
              conn.commit();
          }catch (SQLException e)
          {
    
    
              e.printStackTrace();
          }finally {
    
    
              DBUtils.closeall(conn,null,null);
          }
      }
      //回滚事务
      public static void rollback()
      {
    
    
          Connection conn=null;
          try {
    
    
              conn=getconnection();
              conn.rollback();
          }catch (SQLException e)
          {
    
    
              e.printStackTrace();
          }finally {
    
    
              DBUtils.closeall(conn,null,null);
          }

      }
    public static void closeall(Connection conn, PreparedStatement pst, ResultSet rs){
    
    
        if(rs!=null){
    
    
            try {
    
    
                rs.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }
        }

        if(pst!=null){
    
    
            try {
    
    
                pst.close();
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }
        }

        if(conn!=null){
    
    
            try {
    
    
                conn.close();
                THREAD_LOCAL.remove();//关闭连接后移除已关闭的connection对象
            } catch (SQLException throwables) {
    
    
                throwables.printStackTrace();
            }
        }

    }
}

三层架构

什么是三层架构

表示层:
      命名:XXXView
      职责:收集用户的数据和需求,展示数据
业务逻辑层
	   命名:XXXServiceImpl
	   职责:数据加工处理,调用DAO完成业务实现,控制事务
数据访问层
        命名:XXXDaoImpl
        职责:向业务层提供数据,将业务层加工后的数据同步到数据库

在这里插入图片描述

三层架构项目搭建

utils 存放工具类 DBUtils
entity 存放实体类 
dao 存放DAO接口
    Impl存放DAO接口的实现类
service 存放service接口
	Impl存放service接口的实现类
view 存放程序的启动类

三层架构在idea中的截图

在这里插入图片描述
lib是存放jar包的直接在整个工程下建立,db.properties是在src下建立的,其他包如图所示

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db3?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
username=root
password=123456

PersonDao 接口

package com.blb.dao;

import com.blb.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 select(int id);

    public List<Person> selectAll();
}

PersonDaoImpl类

package com.blb.dao.Impl;

import com.blb.dao.PersonDao;
import com.blb.entity.Person;
import com.blb.utils.DButils;
import com.blb.utils.Dateutils;

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

public class PersonDaoImpl implements PersonDao {
    
    
    @Override
    public int insert(Person person) {
    
    
        Connection conn=null;
        PreparedStatement pst=null;
        String sql="insert into person(name,age,borndate,email,address) values(?,?,?,?,?);";
        conn=DButils.getConnection();
        try {
    
    
            pst= conn.prepareStatement(sql);
            pst.setString(1,person.getName());
            pst.setInt(2,person.getAge());
            pst.setDate(3, Dateutils.UtiltoSql(person.getBorndate()));
            pst.setString(4,person.getEmail());
            pst.setString(5,person.getAddress());
             int i = pst.executeUpdate();
             return i;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            DButils.closeall(null,pst,null);
        }
        return 0;
    }

    @Override
    public int update(Person person) {
    
    
        Connection conn=null;
        PreparedStatement pst=null;
        String sql="update person set name=?,age=?,borndate=?,email=?,address=? where id=?;";
        conn=DButils.getConnection();
        try {
    
    
            pst= conn.prepareStatement(sql);
            pst.setString(1,person.getName());
            pst.setInt(2,person.getAge());
            pst.setDate(3, Dateutils.UtiltoSql(person.getBorndate()));
            pst.setString(4,person.getEmail());
            pst.setString(5,person.getAddress());
            pst.setInt(6,person.getId());
            int i = pst.executeUpdate();
            return i;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            DButils.closeall(null,pst,null);
        }
        return 0;
    }

    @Override
    public int delete(int id) {
    
    
        Connection conn=null;
        PreparedStatement pst=null;
        String sql="delete from person where id=?;";
        conn=DButils.getConnection();
        try {
    
    
            pst= conn.prepareStatement(sql);
            pst.setInt(1,id);
            int i = pst.executeUpdate();
            return i;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            DButils.closeall(null,pst,null);
        }
        return 0;
    }

    @Override
    public Person select(int id) {
    
    
        Connection conn=null;
        PreparedStatement pst=null;
        ResultSet rs=null;
        String sql="select * from person where id=?";
        Person person=null;
        conn=DButils.getConnection();
        try {
    
    
            pst= conn.prepareStatement(sql);
            pst.setInt(1,id);
            rs= pst.executeQuery();
            if(rs.next()){
    
    
                 int id1 = rs.getInt("id");
                 int age = rs.getInt("age");
                String name = rs.getString("name");
                String email = rs.getString("email");
                 String address = rs.getString("address");
                 Date date = rs.getDate("borndate");
                 person=new Person(id1,name,age,date,email,address);
            }
            return person;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            DButils.closeall(null,pst,rs);
        }
        return null;
    }

    @Override
    public List<Person> selectAll() {
    
    
        List<Person> arr=new ArrayList<>();
        Connection conn=null;
        PreparedStatement pst=null;
        ResultSet rs=null;
        String sql="select * from person ";
        Person person=null;
        conn=DButils.getConnection();
        try {
    
    
            pst= conn.prepareStatement(sql);

            rs= pst.executeQuery();
            while (rs.next()){
    
    
                int id1 = rs.getInt("id");
                int age = rs.getInt("age");
                String name = rs.getString("name");
                String email = rs.getString("email");
                String address = rs.getString("address");
                Date date = rs.getDate("borndate");
                person=new Person(id1,name,age,date,email,address);
                arr.add(person);
            }
            return arr;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            DButils.closeall(null,pst,rs);
        }
        return null;
    }
}

PersonService接口

package com.blb.service;

import com.blb.entity.Person;

import java.util.List;

public interface PersonService {
    
    
    public int insert(Person person);

    public  int update(Person person);

    public int delete(int id);

    public Person select(int id);

    public List<Person> selectAll();
}

PersonServiceImpl类

package com.blb.service.Impl;

import com.blb.dao.Impl.PersonDaoImpl;
import com.blb.dao.PersonDao;
import com.blb.entity.Person;
import com.blb.service.PersonService;

import java.util.List;

public class PersonServiceImpl implements PersonService {
    
    
    private PersonDao pd=new PersonDaoImpl();
    @Override
    public int insert(Person person) {
    
    
         int insert = pd.insert(person);
        return insert;
    }

    @Override
    public int update(Person person) {
    
    
         int update = pd.update(person);
        return update;
    }

    @Override
    public int delete(int id) {
    
    
         int delete = pd.delete(id);
        return delete;
    }

    @Override
    public Person select(int id) {
    
    
         Person person = pd.select(id);
        return person;
    }

    @Override
    public List<Person> selectAll() {
    
    
         List<Person> people = pd.selectAll();
        return people;
    }
}

可以看到Service层操作Dao层,方法都是一样的,Dao层操作数据库,但是代码还是很长很冗余
所以对数据库的增删改查操作进行抽取封装DaoUtils

DaoUtils

package com.blb.utils;

import com.blb.advanced.RowMapper;

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 Daoutils<T>{
    
    
    /**
     * 公共处理增删改的方法
     * @param sql 执行的sql语句
     * @param args  参数列表
     * @return
     */
    public  int commonsUpdate(String sql,Object...args){
    
    
        Connection conn=null;
        PreparedStatement pst=null;
         conn = DButils.getConnection();
        try {
    
    
            pst=conn.prepareStatement(sql);
            for(int i=0;i<args.length;i++){
    
    
                pst.setObject(i+1,args[i]);
            }
             int i = pst.executeUpdate();
             return i;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            DButils.closeall(null,pst,null);
        }

        return 0;
    }

    public  List<T> commonsSelect(String sql, RowMapper<T> rowMapper,Object...args)
    {
    
    
        List<T> arr=new ArrayList<>();
        Connection conn=null;
        PreparedStatement pst=null;
        ResultSet rs=null;

        try {
    
    
            conn=DButils.getConnection();
            pst=conn.prepareStatement(sql);

             if(args!=null){
    
    //注意要判断非空否则查询所有的时候会报错误

                 for(int i=0;i<args.length;i++)
                 {
    
    
                     pst.setObject(i+1,args[i]);
                 }
             }
            rs = pst.executeQuery();
             while (rs.next()){
    
    
                 //根据查询到的结果完成orm
                 T t=rowMapper.getRow(rs);
                 arr.add(t);

             }
             return arr;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            DButils.closeall(null,pst,rs);
        }

        return null;
    }
}

在建一个包用于实现查询里面的orm映射,并且使用泛型这样可以供所有的使用

RowMapper 接口

package com.blb.advanced;

import java.sql.ResultSet;

public interface RowMapper<T> {
    
    
    public T getRow(ResultSet rs);
}

PersonRowMapper 实现类

package com.blb.advanced.Impl;

import com.blb.advanced.RowMapper;
import com.blb.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 rs) {
    
    
        Person person=null;
        int id1 = 0;
        try {
    
    
            id1 = rs.getInt("id");
            int age = rs.getInt("age");
            String name = rs.getString("name");
            String email = rs.getString("email");
            String address = rs.getString("address");
            Date date = rs.getDate("borndate");
            person=new Person(id1,name,age,date,email,address);

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

        return null;
    }
}

修改完后的PersonDaoImpl

package com.blb.dao.Impl;
import com.blb.advanced.Impl.PersonRowMapper;
import com.blb.dao.PersonDao;
import com.blb.entity.Person;
import com.blb.utils.Daoutils;

import java.util.List;

public class PersonDaoImpl implements PersonDao {
    
    
    private Daoutils<Person> daoutils=new Daoutils<>();
    @Override
    public int insert(Person person) {
    
    

        String sql="insert into person(name,age,borndate,email,address) values(?,?,?,?,?);";

        Object args[]={
    
    person.getName(),person.getAge(),person.getBorndate(),person.getEmail(),person.getAddress()};
        return daoutils.commonsUpdate(sql,args);

    }

    @Override
    public int update(Person person) {
    
    

        String sql="update person set name=?,age=?,borndate=?,email=?,address=? where id=?;";
        Object args[]={
    
    person.getName(),person.getAge(),person.getBorndate(),person.getEmail(),person.getAddress(),person.getId()};
        return daoutils.commonsUpdate(sql,args);
    }

    @Override
    public int delete(int id) {
    
    

        String sql="delete from person where id=?;";
        return daoutils.commonsUpdate(sql,id);
    }

    @Override
    public Person select(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(),null);
        if(!people.isEmpty()){
    
    
            return people;
        }
        return null;
    }
}

Druid连接池

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

连接池的配置文件

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db3?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
username=root
password=123456
#初始化连接
initialSize=10

#最大连接数量
maxActive=50

#最小空闲连接
minIdle=5

#超时等待时间以毫秒为单位
maxWait=5000

DButils

package com.blb.utils;

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

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

public class DButils {
    
    
    //声明连接池对象
    private static DruidDataSource ds;
    private  static  final  ThreadLocal<Connection> THREAD_LOCAL=new ThreadLocal<>();
    static {
    
    
        //实例化配置对象
        Properties properties=new Properties();
         InputStream inputStream= DButils.class.getResourceAsStream("/db.properties");
        try {
    
    
            properties.load(inputStream);
            ds=(DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    //获取连接对象
    public static Connection getConnection()
    {
    
    
        Connection conn=THREAD_LOCAL.get();
        try {
    
    
            if(conn == null){
    
    
                conn=ds.getConnection();
                THREAD_LOCAL.set(conn);
            }

        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }
    public static void begin(){
    
    
        Connection conn=null;

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

    public static void commit(){
    
    
        Connection conn=null;

        try {
    
    
            conn=getConnection();
            conn.commit();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            closall(conn,null,null);
        }
    }

    public static  void rollback()
    {
    
    
        Connection conn=null;

        try {
    
    
            conn=getConnection();
            conn.rollback();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            closall(conn,null,null);
        }

    }
    public static void closall(Connection conn, PreparedStatement pst, ResultSet rs){
    
    

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

    }
    //返回一个数据源
    public static DataSource getDataSource(){
    
    
            return ds;
    }
}


测试连接池

package com.blb.test;

import com.blb.utils.DButils;

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

public class pooltest {
    
    
    public static void main(String[] args) {
    
    
        for(int i=0;i<15;i++){
    
    
            Connection conn= DButils.getConnection();
            System.out.println(conn);
            try {
    
    
                conn.close();
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

注意连接池的关闭连接并不是关闭而是归还给连接池

Apache的DbUtils使用

Commons DbUtils 是Apache组织提供的一个对JDBC进行简单的封装的开源工具类库,使用它能简化JDBC应用程序开发

简介

DbUtils是java编程中数据库操作使用小工具,小巧,简单,实用
对于数据表的查询操作,可以把结果转换为List,Array,set等集合,便于操作
对于数据表的DML操作,也变得很简单(只需要写sql语句)

DbUtils主要包含

ResultSetHandler接口:转换类接口
		BeanHandler类:实现类,把一条记录转化成对象
		BeanListHandler类:实现类,把多条记录转化成List集合
		ScalarHandler类:实现类,适合获取一行一列的数据
QueryRunner 类执行sql语句的类
		增,删,改:update()
		查询 :query()

DButils

主要多加了一个方法返回数据源的方法,因为queryRunner需要一个数据源作为参数创建对象

package com.blb.utils;

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

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

public class DButils {
    
    
    //声明连接池对象
    private static DruidDataSource ds;
    static {
    
    
        //实例化配置对象
        Properties properties=new Properties();
         InputStream inputStream= DButils.class.getResourceAsStream("/db.properties");
        try {
    
    
            properties.load(inputStream);
            ds=(DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    //获取连接对象
    public static Connection getConnection()
    {
    
    
        try {
    
    
            return ds.getConnection();
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }

    //返回一个数据源
    public static DataSource getDataSource(){
    
    
            return ds;
    }
}

person实体类

package com.blb.entity;

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 void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int 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 + '\'' +
                '}';
    }
}

PersonDao 接口

package com.blb.dao;

import com.blb.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 select(int id);

    public List<Person> selectAll();

    public long count();
}

PersonDaoImpl类

package com.blb.dao.Impl;


import com.blb.dao.PersonDao;
import com.blb.entity.Person;
import com.blb.utils.DButils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

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

public class PersonDaoImpl implements PersonDao {
    
    
    //创建一个QueryRunner对象,并传递一个数据源对象
    QueryRunner queryRunner=new QueryRunner(DButils.getDataSource());
    @Override
    public int insert(Person person) {
    
    

        String sql="insert into person(name,age,borndate,email,address) values(?,?,?,?,?);";

        Object args[]={
    
    person.getName(),person.getAge(),person.getBorndate(),person.getEmail(),person.getAddress()};

        try {
    
    
            return queryRunner.update(sql,args);
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }

        return 0;
    }

    @Override
    public int update(Person person) {
    
    

        String sql="update person set name=?,age=?,borndate=?,email=?,address=? where id=?;";
        Object args[]={
    
    person.getName(),person.getAge(),person.getBorndate(),person.getEmail(),person.getAddress(),person.getId()};
        try {
    
    
            return queryRunner.update(sql,args);
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public int delete(int id) {
    
    

        String sql="delete from person where id=?;";
        try {
    
    
            return queryRunner.update(sql,id);
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public Person select(int id) {
    
    

        String sql="select * from person where id=?";
        try {
    
    
            //把查询到的记录封装成指定对象
            Person query = queryRunner.query(sql, new BeanHandler<Person>(Person.class), id);
            return query;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<Person> selectAll() {
    
    

        String sql="select * from person ";
        try {
    
    
             List<Person> query = queryRunner.query(sql, new BeanListHandler<Person>(Person.class));
            return query;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }
 //查询总人数
    @Override
    public long count() {
    
    
        String sql="select count(*) from person ;";
        try {
    
    
            Long query = queryRunner.query(sql, new ScalarHandler<>());
            return query;
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
        return 0;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_44866153/article/details/108853063
今日推荐