JDBC入门


java database connection:java数据库连接

1.JDBC原生7大步骤

JDBC如何操作DQL语句,操作步骤

//1)导包,注册驱动
Class.forName("com.mysql.jdbc.Driver") ;
//2)获取数据库的连接对象
Connnection conn = DriverManager.getConnection(
		"jdbc:mysql://localhost:3306/库名",
    	"root",
    	"登录数据库的密码"
) ;
//3)准备sql---查询语句
String sql = "select * from 表名" ;
//4)获取执行对象Statement
Statement stmt = conn.createStatement() ;
//5)执行dql语句
ResultSet rs = stmt.executeQuery(sql) ;
//6)遍历结果集的数据
while(rs.next()){
   字段类型 变量名=   rs.getXXX("字段名称") ;
    //或者是 字段类型 变量名 = rs.getXXX(列的索引值) ; //列的索引值1..开始
    //使用这个变量名
}

//7)释放资源
rs.close();
stmt.close() ;
conn.close() ;

1.1 DDL


/**
 * JDBC操作DDL语句  创建表
 */
public class Jdbc_OperatrDDL {
    public static void main(String[] args) throws  Exception{
        //1)导包,注册驱动
        Class.forName("com.mysql.jdbc.Driver")  ;
        //2)获取数据库连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myee_2203_02",
                "root",
                "123456");
        //3)准备sql
        String sql = "CREATE TABLE student("
               + " id INT PRIMARY KEY AUTO_INCREMENT," +
                " NAME VARCHAR(10), " +
                " gender VARCHAR(2), " +
                " address VARCHAR(50), " +
                " hobby VARCHAR(100) " +
                ") " ;
        //4)使用连接对象创建执行对象
        Statement stmt = connection.createStatement();
        //5)执行sql,发送数据库
        int count = stmt.executeUpdate(sql);
        System.out.println("影响"+count+"行") ;
        //6)释放资源
        stmt.close();
        connection.close();
    }
}

1.2 DML

package jdbc_02;

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

/**
 * JDBC操作DDL语句  创建表
 */
public class Jdbc_OperatrDDL {
    public static void main(String[] args) throws  Exception{
        //1)导包,注册驱动
        Class.forName("com.mysql.jdbc.Driver")  ;
        //2)获取数据库连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myee_2203_02",
                "root",
                "123456");
        //3)准备sql
        String sql = "CREATE TABLE student("
               + " id INT PRIMARY KEY AUTO_INCREMENT," +
                " NAME VARCHAR(10), " +
                " gender VARCHAR(2), " +
                " address VARCHAR(50), " +
                " hobby VARCHAR(100) " +
                ") " ;
        //4)使用连接对象创建执行对象
        Statement stmt = connection.createStatement();
        //5)执行sql,发送数据库
        int count = stmt.executeUpdate(sql);
        System.out.println("影响"+count+"行") ;
        //6)释放资源
        stmt.close();
        connection.close();
    }
}

1.3DQL

/**
 * JDBC使用Statement执行对象来操作DQL语句:数据库查询语句
 */
public class Jdbc_Operator_DQL {
    public static void main(String[] args)throws  Exception {

        //需求:查询myee_2203_02 库中学生表的所有信息
        //注册驱动
        Class.forName("com.mysql.jdbc.Driver") ;
        //获取数据库的连接对象
        Connection connection = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/myee_2203_02",
                "root",
                "123456"
        ) ;
        //sql
        String sql ="select * from student" ;
        //获取执行对象
        Statement stmt = connection.createStatement();
        //执行DQL语句
        //ResultSet exceuteQuery(String sql)
        ResultSet rs = stmt.executeQuery(sql);
        System.out.println("学生列表如下:");
        System.out.println("编号\t姓名\t性别\t地址\t爱好");

       /* //第一次获取
        if(rs.next()){ //true,有数据,光标向前移动一行

            //获取数据 ResultSet  通用操作
            //xxx getXxx(int 列的索引值)
            //xxx getXxxx(String 列的名称)
            int id = rs.getInt(1); //获取编号
            String name = rs.getString(2); //获取姓名
            String gender = rs.getString(3); //获取性别
            String addrses = rs.getString(4); //获取地址
            String hobby = rs.getString(5);//获取爱好
            System.out.println(id+"\t\t"+name+"\t"+gender+"\t\t"+addrses+"\t"+hobby);
        }
        //第二次获取
        if(rs.next()){ //true,有数据,光标向前移动一行
            //获取数据 ResultSet  通用操作
            //xxx getXxx(int 列的索引值)
            //xxx getXxxx(String 列的名称)
            int id = rs.getInt("id"); //获取编号
            String name = rs.getString("name"); //获取姓名
            String gender = rs.getString("gender"); //获取性别
            String addrses = rs.getString("address"); //获取地址
            String hobby = rs.getString("hobby");//获取爱好
            System.out.println(id+"\t\t"+name+"\t"+gender+"\t\t"+addrses+"\t"+hobby);
        }*/
        //依次类推
        //不明确循环次数
        while(rs.next()){
            int id = rs.getInt("id"); //获取编号
            String name = rs.getString("name"); //获取姓名
            String gender = rs.getString("gender"); //获取性别
            String addrses = rs.getString("address"); //获取地址
            String hobby = rs.getString("hobby");//获取爱好
            System.out.println(id+"\t\t"+name+"\t"+gender+"\t\t"+addrses+"\t"+hobby);
        }

        //释放资源
        rs.close();
        stmt.close();
        connection.close();
    }
}

2.封装JDBC基本操作的工具类步骤

//在src目录下:类路径   xxx.properties
//driverClass=com.mysql.jdbc.Driver
//url=jdbc:mysql://localhost:3306/库名?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
//username=root
//password=登录的密码

class JdbcUtils{
    
    private static String drierClass = null ;
    private static String url = null ;
    private static String username = null ;
    private static String password = null ;
    
    private JdbcUtils(){}
    
    //提供静态代码块:随着类的加载而加载
    static{
        //创建属性列表:属性集合类  Properties
        Properties prop = new Properties() ;
        //读取配置文件 获取配置文件所在的输入流对象
        InputStream inputStream = JdbcUtils.class.getClassLoader().getResurcesAsStream("xxx.properties") ;
        //将流对象中的加载属性列表中prop
        prop.load(inputStream) ;
        //通过key获取它里面的value
        drierClass = prop.getProperty("driverClass") ;
        url = prop.getProperty("url") ; 
        username = prop.getProperty("username") ;
        password = prop.getProperty("password") ;
        
        //注册驱动
        Class.forName(drierClass) ;
          
    }
    
    //获取连接对象
    public static Connection getConnection(){
        
        Connnection conn = DriverManager.getConnection(url,username,password) ;
        return conn ;
    }
    
    //释放资源--关闭相关系统资源 (发送sql到数据库Statement执行对象,Connection ,ResultSet)
    public static void close(Statement stmt,Connnection conn){
        close(null,stmt,conn) ;
    }
    public  static void close(ResultSet rs,Statement stmt,Connnection conn){
        	
        if(rs!=null){
            try{
                  rs.close() ; 
            }catch(SQLException e){
                e.printStackTrice() ;
            }
          
        }
         if(stmt!=null){
            try{
                  stmt.close() ; 
            }catch(SQLException e){
                e.printStackTrice() ;
            }
          
        }
         if(conn!=null){
            try{
                  conn.close() ; 
            }catch(SQLException e){
                e.printStackTrice() ;
            }
          
        }
       
    }
    
}

3.获取一个类的字节码文件的方式

1)任意java类型的class属性
2)Object类中的getClass();  对象名.getClass()
3)Class.forName("类的全限定名称") ;//包名.类名

4.mysql的驱动包如何注册驱动的?

针对5.1的jar包的com.mysql.jdbc.Driver进行说明

class Driver implements java.sql.Driver{
    
    static{
        
        DriverManager.registerDriver(new Driver()) ; //这块已经使用到了注册驱动的方法
    }
    
}

5.JDBC使用PreparedStatement预编译对象操作数据库的步骤

//原生操作步骤
//1.导包 驱动包:5.1jar/8.0以及它以上的jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver") ;
//3.获取数据库的连接对象
Connection conn = DriverManager.getConnection(
     "jdbc:mysql://localhost:3306/库名?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true",
    "root",
    "登录mysql的密码"
) ;
//4)准备好参数化的sql语句 DML语句
String sql = "insert into 表名 values(?,?,?...)" ;
String sql2 = "update 表名 set 字段名称1 = ?,字段名称2 = ?,字段名称3 = ? where 字段名称 = ?" ;
String sql3 = "delete from 表名 where 字段名称 = ?" ;
//sql语句:参数化的DQL语句
String sql4 = "select * from 表名 " ;
String sql5 = "select * from 表名  where 字段名称 = ?" ;
//...

//5)获取预编译对象,同时将sql发送给数据库
PreparedStatement ps  =   conn.prepareStatement(sql) ;
//6)通过预编译对象,参数赋值
ps.setXXX(占位符号的索引值,XXX类型的实际参数) ;
//7)要么执行DML语句
int count = ps.executeUpdate() ; 
//影响的行数 count
//要么执行的DQL语句
ResultSet rs = ps.executeQuery() ;
while(rs.next()){
    //获取结果数据
    XXX 变量名  = rs.getXXX("列的名称要么列的索引值") ;
}
//释放资源
//执行dql语句,
//执行dml,只需要释放后面两个对象 ps对象以及conn对象
rs.close();
ps.close();
conn.close() ;


6.Statement和PreparedStatement对象的区别

1)执行sql效率区别
	Statement对象:执行sql,每一次将sql都需要发送一次,相对于PreparedStatement对象效率低,不用它的原因
	数据库的性能优化--->减少服务器的交互次数(和数据库的交互次数减少)
	PreparedStatement对象:预编译对象: 执行的参数化的sql,直接先发送给数据库,数据库会进行校验(参数类型,以及参数的字段是哪一列),并且保存在预编译对象中,可以不断的重新赋值;执行sql效率高!
2)是否存在sql注入的区别
	Statement对象:执行的sql语句,都是静态化sql,sql存在字符串拼接,就会导致可能出现sql注入,非常不安全!
			举例
				select * from user where username = '"+变量名+"' and password '"+值...+"' ;
			
	PreparedStatement预编译对象:每次是在自己内存中直接赋值对应的值,sql语句永远是占位符号?
	select * from user where username = ? and password = ? ;
	 不会造成sql注入问题,非常安全的!

7.什么是数据库连接池,数据库连接池的好处是什么

数据库连接池:
       可以分配,释放,管理数据库连接对象,当前某个连接对象释放之后,会归还到连接池中,大大提高了JDBC操作数据库性能!
       弊端:维护成本高; (维护它druid的版本以及监控它的连接数量)
        好处:可以设置参数,将数据库连接池进行调优;
        每一个线程都会使用自己的连接对象!
        前某个连接对象释放之后,会归还到连接池中,等待下一次利用(大大提高了连接对象的使用率)
      
       	在连接池中:会初始化一些连接数量(提供了很多参数)
       	initialSize:初始化数量
       	maxActive:最大激活数量
       	maxWait:最大等多等待时间(毫秒值)
       	maxidle:最大空闲数量
       	minidel:最小空闲数量
       	...
       	...

8.通过Druid(德鲁伊)获取数据源的操作步骤

//1)导包
//2)加入连接池的配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/库名?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
 //3)读取配置文件 
   InputStream inputStream =  当前类.class.getClassLoader().getResourceAsStream("xxx.properties") ;
//4)创建属性集合列表
Properties prop = new Properties() ;
prop.load(inputStream) ;
//5)获取数据源----DruidDataSourceFactory
//public static DataSource createDataSource(Properties prop)
DataSource ds = DruidDataSourceFactory.createDataSource( prop) ;
//DataSource替代了DriverManager: Connection getConnection() ;
//6)获取连接对象
Connection conn = ds.getConnection() ;
//使用连接对象

9.封装jdbc工具类,加入数据库连接池以及ThreadLocal的步骤

//为了模拟真实场景:一个线程使用自己的连接对象---操作数据库
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.qf.hw1.utils.DruidJdbcUtils;

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

/**
 * @version: 1.0
 */
public class DruidJDBCUtils {
    //模拟线程,每一个线程使用自己的connection
    private static ThreadLocal<Connection> t = new ThreadLocal<>();
    //声明一个DataSource类型的变量
    private static DataSource ds;

    //无参构造私有化
    private DruidJDBCUtils() {
    }

    //静态代码块
    static {

        try {
            //创建属性集合列表
            Properties pro = new Properties();
            //直接读取连接池的配置文件
            InputStream inputStream = DruidJDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            //将字节输入流的内容加载属性列表中
            pro.load(inputStream);
            //工厂类获取数据源对象
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
        //封装一个功能:获取数据库的连接对象
        public static DataSource getDataSource() {
            return ds;
        }

    public static Connection getConnection(){
        //1)首先要从当前线程中获取连接对象
        try {
            Connection conn = t.get();
            //2)判断conn是空的
            if(conn==null){
                //当前线程中没有开始绑定连接对象
                //3)从数据源连接池获取连接对象
                conn = ds.getConnection() ;
                //4)将当前连接对象绑定给自己的线程中
                t.set(conn);
            }
            return conn ;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  null ;
    }

    //封装释放资源
    public static void close(PreparedStatement ps,Connection conn){
        close(null,ps,conn);
    }
    public static void close(ResultSet rs, PreparedStatement ps,Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

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

        if(conn!=null){
            try {
                conn.close();
                //需要将自己线程中的连接对象解绑
                t.remove();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) {
        // DataSource dataSource = DruidJdbcUtils.getDataSource();
        //  System.out.println(dataSource);
        //获取连接对象
        Connection connection = DruidJdbcUtils.getConnection();
        System.out.println(connection);
    }

}

10.单元测试

步骤:

1.导包junit核心包以及hmrecrest-core 依赖包
2)测试某个功能
	编写测试用例----编写一个单元测试方法
	这个方法没有返回值类型,没有参数
3)需要标记这个方法为单元测试方法,需要在方法上面加入@Test注解
4)在junit包下一个断言Assert里面很多的方法来断言某个功能的结果
	是否和预期结果一致,如果一致,说明断言成功;否则失败! (如果测试自己的功能,不用断言,可以直接接口多态测试数据是否存在!)

举例:

员工类


/**
 * @Author: txh
 * @Date: 2022/5/18 - 05 - 18 - 17:58
 * @Description: hw1
 * @version: 1.0
 */
public class Emp {
    private int id;
    private String name;
    private int age;
    private String gender;
    private String address;
    private double salary;

    public Emp(int id, String name, int age, String gender, String address, double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.address = address;
        this.salary = salary;
    }

    public Emp() {
    }


    @Override
    public String toString() {
        return "emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", address='" + address + '\'' +
                ", salary=" + salary +
                '}';
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getGender() {
        return gender;
    }

    public String getAddress() {
        return address;
    }

    public double getSalary() {
        return salary;
    }

    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 setGender(String gender) {
        this.gender = gender;
    }

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

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

接口:


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

/**
 * @Author: txh
 * @Date: 2022/5/19 - 05 - 19 - 20:40
 * @Description: com.qf2.hw1
 * @version: 1.0
 */
public interface EmpDao {
    void add(Emp emp) throws SQLException;
    void sub() throws SQLException;
    void update() throws SQLException;
    List<Emp> select() throws SQLException;
}

实现类:


import com.qf2.druid.DruidJDBCUtils;


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

/**
 * @Author: txh
 * @Date: 2022/5/19 - 05 - 19 - 19:52
 * @Description: com.qf2.hw1
 * @version: 1.0
 */
public class EmpDaoimpl implements EmpDao{

    /**
     * 添加员工的方法
     * @throws SQLException
     */
    @Override
    public  void add(Emp emp) throws SQLException {
        //1.获取连接对象
        Connection connection = DruidJDBCUtils.getConnection();
        //2.获得参数化的sql
        String sql = "insert into emp2 values(?,?,?,?,?,?)";
        //3.赋值
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,emp.getId());
        preparedStatement.setString(2,emp.getName());
        preparedStatement.setInt(3,emp.getAge());
        preparedStatement.setString(4,emp.getGender());
        preparedStatement.setString(5,emp.getAddress());
        preparedStatement.setDouble(6,emp.getSalary());
        //4.
        int i = preparedStatement.executeUpdate();
        System.out.println("影响了"+i+"行");
        DruidJDBCUtils.close(preparedStatement,connection);
    }

    /**
     * 删除员工的方法
     */
    @Override
    public  void sub() throws SQLException {
        Connection connection = DruidJDBCUtils.getConnection();
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要删除的id:");
        int id = scanner.nextInt();
        String sql = "delete from emp2 where id=?;";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,id);
        int i = preparedStatement.executeUpdate();
        System.out.println("影响了"+i+"行");
        DruidJDBCUtils.close(preparedStatement,connection);
    }
    @Override
    public  void update() throws SQLException {
        Connection connection = DruidJDBCUtils.getConnection();
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要更新的id:");
        int id = scanner.nextInt();
        String sql = "update emp2 set name = '孙悟空' where id=?;";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,id);
        int i = preparedStatement.executeUpdate();
        System.out.println("影响了"+i+"行");
        DruidJDBCUtils.close(preparedStatement,connection);
    }

    @Override
    public List<Emp> select() throws SQLException {
        Connection connection = DruidJDBCUtils.getConnection();
        String sql = "select * from emp2";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        List<Emp> list = new ArrayList<>();
        Emp emp = null;
        while(resultSet.next()){
            emp = new Emp();
           emp.setId(resultSet.getInt(1));
           emp.setName(resultSet.getString(2));
           emp.setAge(resultSet.getInt(3));
           emp.setGender(resultSet.getString(4));
           emp.setAddress(resultSet.getString(5));
           emp.setSalary(resultSet.getDouble(6));
           list.add(emp);
        }
        DruidJDBCUtils.close(resultSet,preparedStatement,connection);
        return list;
    }
}

测试类:


import org.junit.Before;

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

/**
 * @Author: txh
 * @Date: 2022/5/19 - 05 - 19 - 20:52
 * @Description: com.qf2.hw1
 * @version: 1.0
 */

public class Test {
    EmpDaoimpl empDaoimpl;
    @Before
    public  void createEmpDao(){
       empDaoimpl = new EmpDaoimpl();
    }
    @org.junit.Test
    public void addTest() throws SQLException {
        Emp emp = new Emp(6, "易烊千玺", 20, "男", "北京", 50000);
        empDaoimpl.add(emp);
    }
    @org.junit.Test
    public void subTest() throws SQLException {
        empDaoimpl.sub();
    }
    @org.junit.Test
    public void updateTest() throws SQLException { EmpDaoimpl empDaoimpl = new EmpDaoimpl();
        empDaoimpl.update();
    }
    @org.junit.Test
    public void selectTest() throws SQLException { EmpDaoimpl empDaoimpl = new EmpDaoimpl();
        List<Emp> select = empDaoimpl.select();
        for (Emp emp : select) {
            System.out.println(emp);
        }
    }
}

@After//在执行@Test标记的这个方法之后执行
@Before//现在执行这个方法

11.事务

import com.qf.hw2.utils.DruidJDBCUtils;


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

/**
 * @author Kuke
 * @date 2022/5/20 11:33
 * 现在需要使用JDBC方式控制事务:
 * 事务: 针对关系型数据库的一种机制
 *  就是在执行业务操作过程中,同时执行多个sql或者多张表(添加/删除/修改),这些sql语句要么同时执行成功;
 *  要么同时执行失败;
 *
 *  张三给赵又廷转账---sql全部都是使用参数化的sql语句
 *
 *
 *  转账的方法(也可以自定义的方法)
 *  public void transfer(String toName,String reveiveName,int money)
 */
public class JDBCTransactionDemo {
    public static void main(String[] args) {

        //声明Connection类型变量
        Connection connection = null ;
        PreparedStatement ps = null ;
        PreparedStatement ps2 = null ;
        try {
            //没有通过jdbc管理事务-----当同时执行多条sql,中间如果存在异常,第一条件语句成功了,第二条数据失败;
            // 转账业务失败----->应该在jdbc操作转账的业务中加入事务操作!


            //使用Jdbc控制事务--->通过获取连接对象之后,加入事务的方法
            //通过工具类获取连接对象
             connection = DruidJDBCUtils.getConnection();
            //开启事务---->利用Connection的功能void setAutoCommit(boolean autoCommit):默认自动提交
            //参数为false:禁用自动提交,需要手动提交事务
            connection.setAutoCommit(false) ;

            //准备sql---参数化sql
            String sql = "update account set balance = balance - ? where id = ?" ;
            //获取预编译对象
            ps = connection.prepareStatement(sql);
            //参数赋值
            ps.setInt(1,500) ;
            ps.setInt(2,1) ;

            String sql2 = "update account set balance = balance + ? where id = ?" ;
            //获取预编译对象
            ps2 = connection.prepareStatement(sql2);
            ps2.setInt(1,500) ;
            ps2.setInt(2,2);

            //分别执行更新操作
            int count = ps.executeUpdate();

            int i = 10/0 ;

            int count2 = ps2.executeUpdate();
            System.out.println(count+"---"+count2);


            //提交事务: 如果没有问题,提交事务---数据在能永久更新
            //Connection对象的方法:void commit()

        } catch (Exception e) {
            System.out.println("执行catch语句");
            //出现异常,程序执行catch语句
            //事务回滚
            //连接对象的方法void rollback():回滚到默认在更新之前的操作
            try {
                connection.rollback() ;
            } catch (SQLException ex) {
                ex.printStackTrace();
            }

            e.printStackTrace();
            /*System.out.println("异常抛出了");*/
        }finally {
            //任何情况下finally中的代码一定会执行的,除非 只执行这个语句之前,jvm退出了 System.exit(0) ;
            try {
                connection.commit();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            //释放资源
            DruidJDBCUtils.close(ps,connection);
            DruidJDBCUtils.close(ps2,connection);

        }


    }
}

12.引入commons-dbutils工具类库以及使用

qr.ruery这个方法的形参中的接口ResultSetHandler的实现类常用的有三种
BeanListHandler返回一个集合
BeanHandler返回一个对象实例
ScalarHandler返回一个Object对象,使用的时候需要转型
commons-dbutils的官网地址: Apache组织机构旗下的开源的工具类库
https://commons.apache.org/proper/commons-dbutils/
就是被用来完成jdbc操作,简化了jdbc操作的一种书写格式(查询多条记录,将这些记录封装List中)
针对原生Jdbc的建议封装

完成jdbc操作
使用步骤:
1)需要导入核心的jar包 commons-dbtils.jar 
          mysql驱动jar包
          连接池--druid的jar包
          junit单元测试:核心包junit.jar以及依赖包
          
          

2)有关commons-dbtils.jar 核心接口以及核心类有哪些
 使用的执行对象:操作数据库
 org.apache.commons.dbutils.QueryRunner 里面封装就是PreparedStatement
 两个通用的方法
        query(xxx,ResultSetHandler rsh):针对dql语句来完成查询操作
        update(xxx,xx):针对dml域操作:insert into,update,delete from ....
        
        
 核心接口:ResultSetHandler:针对结果集的处理
    
很多很多实现类
BeanListHandler:可以将查询的多条记录封装到List集合中

接口:

import com.qf.hw1.pojo.Emp;

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

/**
 * @Author: txh
 * @Date: 2022/5/20 - 05 - 20 - 14:51
 * @Description: com.qf.dao
 * @version: 1.0
 */
public interface EmoDao {
    /**
     * 查询全部员工的方法
     * @return 集合
     * @throws SQLException
     */
    List<Emp> findAll() throws SQLException;

    /**
     * 查询一个员工的方法
     * @return
     */
    Emp findEmp(int id) throws SQLException;

    /**
     * 增加员工信息的方法
     * @param emp
     */
    void addEmp(Emp emp) throws SQLException;

    /**
     * 根据id删除员工的方法
     * @param id
     */
    void deleteEmp(int id) throws SQLException;

    /**
     * 更新员工
     * @param
     */
    void updateEmp(Emp emp) throws SQLException;

    /**
     * 获得emp2表中总记录数
     * @return
     */
    int getTotalCount() throws SQLException;
}

实现类:

package com.qf.hw1.dao.impl;

import com.qf.hw1.dao.EmoDao;
import com.qf.hw1.pojo.Emp;
import com.qf.hw1.utils.DruidJDBCUtils;

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;

/**
 * @Author: txh
 * @Date: 2022/5/20 - 05 - 20 - 14:54
 * @Description: com.qf.dao.impl
 * @version: 1.0
 */
public class EmpDaoImpl implements EmoDao {
    @Override
    public List<Emp> findAll() throws SQLException {
        //1.导包
        //2.创建数据库的执行对象
        QueryRunner query = new QueryRunner(DruidJDBCUtils.getDataSource());
        //3.准备参数化的sql语句
        String sql = "select * from emp2 " ;
        //4.执行它的通用方法
        List<Emp> list = query.query(sql, new BeanListHandler<Emp>(Emp.class));
        return list;
    }

    @Override
    public Emp findEmp(int id) throws SQLException {
        //1.创建数据库的执行对象
        QueryRunner queryRunner = new QueryRunner(DruidJDBCUtils.getDataSource());
        //2.准备参数化的sql语句
        //String sql = "select name=?,age=?,gender=?,address=?,salary=? from emp2 where id = ? " ;
        String sql = "select * from emp2 where id = ? " ;

        //执行通用方法
        Emp emp = queryRunner.query(sql, new BeanHandler<Emp>(Emp.class), id);
        return emp;
    }

    @Override
    public void addEmp(Emp emp) throws SQLException {
        //1.创建数据库的执行对象
        QueryRunner queryRunner = new QueryRunner(DruidJDBCUtils.getDataSource());
        //2.准备好参数化的sql语句
        String sql = "insert into emp2 (name,age,gender,address,salary) values (?,?,?,?,?) ;" ;
        //3.执行方法
        int i = queryRunner.update(sql,
                emp.getName(),
                emp.getAge(),
                emp.getGender(),
                emp.getAddress(),
                emp.getSalary());
        System.out.println("影响了"+i+"行");
    }

    @Override
    public void deleteEmp(int id) throws SQLException {
        //1.创建数据库的执行对象
        QueryRunner queryRunner = new QueryRunner(DruidJDBCUtils.getDataSource());
        //2.准备好参数化的sql语句
        String sql = "delete from emp2 where id = ? ;" ;
        //3.执行方法
        int i = queryRunner.update(sql, id);
        System.out.println("影响了"+i+"行");
    }

    @Override
    public void updateEmp(Emp emp) throws SQLException {
        //1.创建数据库的执行对象
        QueryRunner queryRunner = new QueryRunner(DruidJDBCUtils.getDataSource());
        //2.准备好参数化的sql语句
        String sql = "update emp2 set name=?,age=?,gender=?,address=?,salary=? where id=? ;" ;
        //3.执行方法
        int i = queryRunner.update(sql,
                emp.getName(),
                emp.getAge(),
                emp.getGender(),
                emp.getAddress(),
                emp.getSalary(),
                emp.getId());
        System.out.println("影响了"+i+"行");
    }

    @Override
    public int getTotalCount() throws SQLException {
        //1.创建数据库的执行对象
        QueryRunner queryRunner = new QueryRunner(DruidJDBCUtils.getDataSource());
        //2.准备好参数化的sql语句
        String sql = "select count(id) from emp2 ;" ;
        //3.执行方法
        //执行sql:将查询的这条记录封装到Employee类中
        // public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
        //参数1:sql语句
        //参数2:结果集的处理:BeanHandler对象    //有参构造 public BeanHandler<T>(Class<T> class)
        //参数3:给占位符号 赋值
        Object o = queryRunner.query(sql, new ScalarHandler<>());
        String s = String.valueOf(o);
        int i = Integer.parseInt(s);
        return i;
    }
}

测试类:

package com.qf.hw1.Test;

import com.qf.hw1.dao.impl.EmpDaoImpl;
import com.qf.hw1.pojo.Emp;
import org.junit.Before;
import org.junit.Test;

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

/**
 * @Author: txh
 * @Date: 2022/5/20 - 05 - 20 - 15:01
 * @Description: com.qf.Test
 * @version: 1.0
 */
public class Test01 {
    EmpDaoImpl emoDaoimpl ;
    @Before
    public void createEmpDaoObject(){
        emoDaoimpl = new EmpDaoImpl();
    }
    @Test
    public void  testFindAll() throws SQLException {
        List<Emp> list = emoDaoimpl.findAll();
        if(list!=null){
            for (Emp emp : list) {
                System.out.println(emp);
            }
        }
    }
    @Test
    public void testAddEmp() throws SQLException {
        Emp emp = new Emp("欧豪",26,"男","上海",20000);
//        emp.setName("王雷");
//        emp.setAge(26);
//        emp.setGender("男");
//        emp.setSalary(5000);
//        emp.setAddress("北京");

        emoDaoimpl.addEmp(emp);
    }

    @Test
    public void testDeleteEmp() throws SQLException {
        emoDaoimpl.deleteEmp(9);
    }

    @Test
    public void testFindEmp() throws SQLException {
        Emp emp = emoDaoimpl.findEmp(10);
        if(emp!=null){
            System.out.println(emp);
        }
    }

    @Test
    public void testUpdate() throws SQLException {
        Emp emp = new Emp(10,"兵兵", 23, "男", "渭南", 12000);
        emoDaoimpl.updateEmp(emp);
    }

    @Test
    public void testGetTotalCount() throws SQLException {
        int totalCount = emoDaoimpl.getTotalCount();
        System.out.println(totalCount);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值