java _JDBC 开发

news2024/9/25 17:22:32

目录

一.封装JDBCUtiles

二.事务

 三.批处理

四.数据库连接池

  C3P0

Druidf(德鲁伊)阿里

五.Apache-DBUtiles

六.Apache-DBUtils

七.DAO 和增删改查 通用方法 - BasicDao

一.封装JDBCUtiles

说明:在jdbc操作中,获取连接和释放资源,是经常使用到,可以将其封装JDBC连接的,工具类JDBCUtils

package com.tianedu.jdbc.utils;

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

/**
 * @author tian
 * 这是一个工具类 完成MySQL的连接和关闭资源
 *
 */
public class JDBCUtils {
    // 定义相关的属性(4个),因为只需要一份,我们做出Static
    private static  String user;     // 用户名
    private static String password;  // 密码
    private static String url;     //url
    private static String driver;  //驱动名称
    //在static 代码块去初始化
    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src\\mysql.properties"));
            //读取相关的属性值
            user =  properties.getProperty("user");
            password = properties.getProperty("password");
            url =  properties.getProperty("url");
            driver =  properties.getProperty("driver");
        } catch (IOException e) {
            //在实际开发中,我们可以这样处理
            //1.将编译异常转换成 运行异常
            //2.这里调用者可以选择捕获该异常,也可以选择默认异常,比较方便。
            throw new RuntimeException(e);
//            e.printStackTrace();
        }
    }
//   连接数据库 返回一个Connection
    public static Connection getConnection(){
        try {
            return DriverManager.getConnection(url,user,password);
        } catch (SQLException e) {
//            throwables.printStackTrace();
            //将编译异常转换成 运行异常,调用者可以捕获该异常,也可以选择默认处理该异常,比较方便
            throw new RuntimeException(e);
        }
    }
    //关闭相关的资源
    /*
    1.ResultSet 结果集
    2.Statement 或者 PreparedStatement
    3.关闭Connection
    4.如果需要关闭资源,就传入对象,否则传入null
     */
    public static void  close(ResultSet set, Statement statement,Connection connection){
        //判断是否为null
        try {
            if(set != null){
                set.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null){
                connection.close();
            }
        } catch (SQLException e) {
            //将编译异常转成运行异常抛出
            throw new RuntimeException(e);
        }
    }
}

使用工具类 JDBCUtils

package com.tianedu.jdbc.utils;

import org.junit.Test;

import java.sql.*;

/**
 * @author tian
 * 该类演示如何使用JDBCUtile工具类完成DML 和 select
 *
 *
 */
public class JDBCUtils_Use {
    public static void main(String[] args) {
        //测试

    }
    @Test
    public void testSelect(){
        //1.得到连接
        Connection connection = null;
        //2.组织一个sql
        String sql  = "select * from actor where id = ?";
        //测试 select
        PreparedStatement preparedStatement = null;
        ResultSet set = null;
        //3.创建PrepareStatement 对象

        try {
            connection = JDBCUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,2);  // 给问号赋值
            //执行 得到结果集
            set = preparedStatement.executeQuery();
            //遍历该结果集
            while(set.next()){
                int  id = set.getInt("id");
                String name = set.getString("name");
                String sex = set.getString("sex");
                Date borndate = set.getDate("borndate");
                String phone = set.getString("phone");
                System.out.println(id + "\t" + name + "\t" + sex + "\t" + borndate + "\t" + phone );
            }
        } catch (SQLException e) {
          e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtils.close(set,preparedStatement,connection);
        }
    }




    @Test
    public void testDML() {
        // insert update delete
        //1.得到连接
        Connection connection = null;
        //2.组织一个sql语句
        String sql = "update actor set name = ? where id = ?";
        PreparedStatement preparedStatement = null;
        //3.创建一个PreparedStatement 对象
        try {
            connection = JDBCUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
         // 给占位符 赋值
         preparedStatement.setString(1,"周星驰");
         preparedStatement.setInt(2,1);
         //执行
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtils.close(null,preparedStatement,connection);
        }
    }
}

二.事务

应用实例,模拟经典的转账业务

  • 不使用事可能出现的问题模拟,模拟经典的转账业务 
package com.tianedu.jdbc.transaction_;

import com.tianedu.jdbc.utils.JDBCUtils;
import org.junit.Test;

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

/**
 * @author tian
 * 演示在JDBC中如何使用事务

 */
public class Transaction_ {
    @Test
    public void noTransaction_(){
        //操作转账的业务
        //1.得到连接
        Connection connection = null;
        //2.组织一个sql语句
        String sql = "update account  set balance = balance -100 where id = 1";
        String sql2 = "update account  set balance = balance + 100 where id = 2";
        // 创建 PreparedStatement 对象
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.executeUpdate(); // 执行第一条sql语句

            int i = 1/0;   // 抛出异常 下面的代码不在执行
            preparedStatement = connection.prepareStatement(sql2);
            preparedStatement.executeUpdate(); // 执行第二条 sql2 语句
        } catch (SQLException e) {
          e.printStackTrace();
        } finally {
            JDBCUtils.close(null,preparedStatement,connection);
        }
    }
    // 事务来解决
    @Test
    public void useTransaction() {
        //1. 连接事务
        Connection connection = null;
        //2.组织sql
        String sql = "update account  set balance = balance -100 where id = 1";
        String sql2 = "update account  set balance = balance + 100 where id = 2";
        //3.创建PrepareStatement 对象
        PreparedStatement preparedStatement = null;
        try {
            connection = JDBCUtils.getConnection();
            // 将connection 设置为不自动提交
            connection.setAutoCommit(false);   //相当于开始事务
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.executeUpdate(); // 执行sql

            preparedStatement = connection.prepareStatement(sql2);
            preparedStatement.executeUpdate(); //执行sql2

            //这里提交事务
            connection.commit();

        } catch (SQLException e) {
            //这里我们可以进行回滚,即撤销执行的sql
            //默认回滚到事务开始的状态
            System.out.println("执行发生了异常,撤销执行的sql");
            try {
                connection.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            } finally {
            }
            e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtils.close(null,preparedStatement,connection);
        }


    }
}

 三.批处理

  • 当需要成批插入或者更新记录时。可以采用java 的批处理更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比较单独提交处理更有效率。
  • JDBC的批处理语句包括下面方法:addBatch() 添加需要批处理的sql语句或参数       executeBatch() 执行批批量处理的语句                                                                                        clearBatch() 清空批处理包的语句
  • JDBC连接MySQL时,如果需要使用批处理功能,请在url中加参数? rewriteBatchedStatements = true
  • 批处理往往和PreparedStatement 一起搭配使用,可以减少编译次数,有减少运行次数,效率大大提高 
  • 如果要批量处理  需要修改 配置文件 jdbc.properties url=jdbc:mysql://localhost:3306/数据库? rewriteBatchedStatements = true
package com.tianedu.jdbc.batch_;

import com.tianedu.jdbc.utils.JDBCUtils;
import org.junit.Test;

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

/**
 * @author tian
 * 演示Java的批处理
 */
public class Batch_ {
    @Test
    //传统的方法添五千条数数据到admin2
    public void noBatch() throws SQLException {
        //得到连接
        Connection connection = JDBCUtils.getConnection();
        //sql
        String sql = "insert into admin2 values(null,?,?)";
        //使用connect创建一个prepareStatement()
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        System.out.println("开始时间");
        long  start = System.currentTimeMillis(); // 开始时间
        for (int i = 0; i<= 5000; i++){
            preparedStatement.setString(1,"jack"+i);
            preparedStatement.setString(2,"666");
            preparedStatement.executeUpdate();
        }
        long end = System.currentTimeMillis();
        System.out.println("传统的方式 耗时="+ (end - start));
        //关闭连接
        JDBCUtils.close(null,preparedStatement,connection);

    }
    //使用批量处理方式添加数据
    @Test
    public void batch() throws SQLException {
        //获得连接
        Connection connection = JDBCUtils.getConnection();
        //写sql语句
        String sql = "insert into admin3 values(null,?,?)";
        //获得preparedStatement
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        System.out.println("开始执行");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            preparedStatement.setString(1,"tom+i");
            preparedStatement.setString(2,"777");
         //   preparedStatement.executeUpdate(); // 执行
            //将sql语句加入到批处理包中
             preparedStatement.addBatch();
             /*
             1.第一创建ArrayList —— elementDate => object[]
             2.elementDate => object[] 就会存放我们预处理的sql语句
             3.当elementDate满后,就按照1.5扩容
             4.当添加到指定的值后就执行批量处理
             5.批量处理会减少发生sql 语句的网络开销,而且减少编码的次数,因此效率高
              */
            //当有一千条记录时候在批量执行
            if ((i+1) % 1000 == 0) { // 说明满一千条 批量执行
                preparedStatement.executeBatch();
                //清空一把
                preparedStatement.clearBatch();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("批量执行方式  耗时 = " + (end - start));
        //关闭连接
        JDBCUtils.close(null,preparedStatement,connection);
    }
}

四.数据库连接池

传统获取Connection问题分析

  1. 传统的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将connection 加载到内存中,在验证ip地址,用户名和密码(0.05s~1s时间)需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接操i在将占用很多的数据系统资源,容易造成服务器崩溃。
  2. 每一次数据库连接,使用完成后都得断开,如果程序出现异常而为关闭,将导致数据库内存泄漏,最终将导致重启数据库
  3. 传统获取连接的方式,不能控制创建的连接数量,如来连接过多,也可能导致内存泄露,mysql奔溃
  4. 解决传统数据库中的数据库连接问题,可以采用数据库连接池技术(connection pool)

数据库连接池基本介绍

  1. 预先在缓冲区中放入一数量的连接,当需要建立数据库连接时,只需从"缓冲池"中取出一个,使用完毕之后在放回去
  2. 数据库连接池负责分配,管理和释放数据库连接,它允许程序重复使用一个现有的数据库连接,而不是重新建立一个
  3. 当应用程序向连接池请求将被加入到等待队列中  

数据库连接池种类

  1. JDBC的数据库连接池使用java.x.sql.DataSource 来表示,DataSource只是一个接口,该接口通常由第三方提高实现  会提供相应的jar 包
  2. C3p0 数据库连接池,速度相对较慢,稳定性不错
  3. DBCP数据库连接驰,速度相对c3p0较快,但不稳定
  4. Proxool数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
  5. BoneCP 数据库连接池,速度快
  6. Druid(德鲁伊) 是阿里提供的数据库连接池,集DBCP,C3P0吗,Proxool优点于一深的数据库连接池
  C3P0
package com.tianedu.jdbc.datasource;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * @author tian
 *
 * 演示c3p0的使用
 */
public class C3P0_ {
    @Test

    //方式1  相关的参数在程序中指定  user url  password 等
    public void testC3p0_01() throws Exception {
        //1.创建一个数据源对象
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        //2.通过配置文件获取相关信息 MySQL.properties 获取相关的连接信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\mysql.properties"));
        //获取相关的属性
        String   user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String url = properties.getProperty("url");
        String driver = properties.getProperty("driver");

        //给数据源 comboPooledDateSource  设置相关的参数
        //连接的管理是由 comboPooledDataSource帮我们管理的
        comboPooledDataSource.setDriverClass(driver);
        comboPooledDataSource.setJdbcUrl(url);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setPassword(password);

        // 设置初始化连接数
        comboPooledDataSource.setInitialPoolSize(10);
        //最大连接数
        comboPooledDataSource.setMaxPoolSize(50);
        //测试连接池的效率
        long  start = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            Connection connection = comboPooledDataSource.getConnection();//这个方法是从 DateSource 接口实现的
//            System.out.println("连接成功");
            connection.close();
        }
       long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
    // 方式2 使用配置文件模板来完成
    // 将c3p0 拷贝到 src 目录下
    //该文件指定了 连接数据库和连接池的线管参数
    @Test
    public void testC3PO_02() throws SQLException {
        //使用配置文件
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("tian");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            Connection connection = comboPooledDataSource.getConnection();
            connection.close();
        }
        long end = System.currentTimeMillis();
        System.out.println(end -start);
    }
}
Druidf(德鲁伊)阿里
package com.tianedu.jdbc.datasource;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;

/**
 * @author tian
 */
public class Druid_ {
    @Test
    //测试德鲁伊的使用
    public void testDruid() throws Exception {
         // 1.加入Druid jar 包
        // 加入配置文件 将该文件拷贝到src目录下  druid.properties
        //3.创建一个 properties 对象,用来读取配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\druid.properties"));
        //4.创建一个指定参数的数据库连接池,德鲁伊的连接池
        DataSource dataSource =
                DruidDataSourceFactory.createDataSource(properties);
        //拿到连接
        Connection connection = dataSource.getConnection();
        System.out.println("连接成功");
        connection.close();
    }
}

//创建德鲁伊数据库连接池

package com.tianedu.jdbc.datasource;

import com.alibaba.druid.pool.DruidDataSourceFactory;

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

/**
 * @author tian
 * 基于德鲁伊数据库池连接的工具类
 */
public class JDBCUtilsByDruid {
    private static DataSource ds;
    //在静态代码块完成ds   的初始化
    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src:druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
        // 编写getConnection方法
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    //关闭连接 是将连接放回到连接池中,close 不是真的断掉连接
    //而是把使用的Connection对象放回到连接池
    public static void  close(ResultSet resultSet, Statement statement,Connection connection){
        try {
            if (resultSet != null){
                resultSet.close();
            }
            if (statement != null){
                statement.close();
            }
            if (connection != null){
                connection.close();
            }
        } catch (SQLException e) {
           throw new RuntimeException(e);
        }


    }
}
package com.tianedu.jdbc.datasource;

import com.alibaba.druid.pool.DruidDataSourceFactory;

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

/**
 * @author tian
 * 基于德鲁伊数据库池连接的工具类
 */
public class JDBCUtilsByDruid {
    private static DataSource ds;
    //在静态代码块完成ds   的初始化
    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src\\druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
        // 编写getConnection方法
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    //关闭连接 是将连接放回到连接池中,close 不是真的断掉连接
    //而是把使用的Connection对象放回到连接池
    public static void  close(ResultSet resultSet, Statement statement,Connection connection){
        try {
            if (resultSet != null){
                resultSet.close();
            }
            if (statement != null){
                statement.close();
            }
            if (connection != null){
                connection.close();
            }
        } catch (SQLException e) {
           throw new RuntimeException(e);
        }


    }
}
package com.tianedu.jdbc.datasource;

import org.junit.Test;

import java.sql.*;

/**
 * @author tian
 */
public class JDBCUtilsByDruid_USE {
    @Test
    public void testSelect(){
        System.out.println("使用德鲁伊的方式完成");
    // 1.得到连接
        Connection connection = null;
        //2.组织一个sql
        String sql = "select * from actor where id = ?";
        PreparedStatement preparedStatement = null;
        ResultSet set = null;
        //3.创建PreparedStatement 对象
        try {
            connection = JDBCUtilsByDruid.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,5);
            set = preparedStatement.executeQuery();
            //遍历该结果集
            while (set.next()){
                int id = set.getInt("id");
                String name = set.getString("name");
                String sex = set.getString("sex");
                Date borndate = set.getDate("brondate");
                String phone = set.getString("phone");
                System.out.println(id + "\t" + name + "\t" + sex + "\t" + borndate + "\t" + phone );


            }
        } catch (SQLException e){
            e.printStackTrace();
        }finally {
            //关闭资源
            JDBCUtilsByDruid.close(set,preparedStatement,connection);
        }
    }
}

五.Apache-DBUtiles

  • 关闭connection 后,resultSet 结果无法使用
  • resultSet 不利于数据的管理
  • 示意图

 使用土方法来解决  来完成分装

package com.tianedu.jdbc.datasource;

import org.junit.Test;

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

/**
 * @author tian
 */
@SuppressWarnings({"all"})
public class JDBCUtilsByDruid_USE {
    @Test
    public void testSelect(){
        System.out.println("使用德鲁伊的方式完成");
    // 1.得到连接
        Connection connection = null;
        //2.组织一个sql
        String sql = "select * from actor where id >= ?";
        PreparedStatement preparedStatement = null;
        ResultSet set = null;
        //3.创建PreparedStatement 对象
        try {
            connection = JDBCUtilsByDruid.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,1);
            set = preparedStatement.executeQuery();

//            connection.close();
            //遍历该结果集
            while (set.next()){
                int id = set.getInt("id");
                String name = set.getString("name");  //getName()
                String sex = set.getString("sex");
                Date borndate = set.getDate("borndate");
                String phone = set.getString("phone");
                System.out.println(id + "\t" + name + "\t" + sex + "\t" + borndate + "\t" + phone );


            }
        } catch (SQLException e){
            e.printStackTrace();
        }finally {
            //关闭资源
            JDBCUtilsByDruid.close(set,preparedStatement,connection);
        }
    }
    //使用土方法来解决 ResultSet => 封装 => ArrayList
    @Test
    public ArrayList<Actor> testSelectToArrayList(){
        System.out.println("使用德鲁伊的方式完成");
        // 1.得到连接
        Connection connection = null;
        //2.组织一个sql
        String sql = "select * from actor where id >= ?";
        PreparedStatement preparedStatement = null;
        ResultSet set = null;
        //创建一个ArrayList
        ArrayList<Actor> list = new ArrayList<>();  // 创建ArrayList 对象,存放actor 对象


        //3.创建PreparedStatement 对象
        try {
            connection = JDBCUtilsByDruid.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,1);
            set = preparedStatement.executeQuery();

//            connection.close();
            //遍历该结果集
            while (set.next()){
                int id = set.getInt("id");
                String name = set.getString("name");  //getName()
                String sex = set.getString("sex");
                Date borndate = set.getDate("borndate");
                String phone = set.getString("phone");
                //把得到的resultSet 分装到 Actor对象  放入到List 集合
                list.add(new Actor(id,name,sex,borndate,phone));
            }

            System.out.println("list 集合数据=" + list);
        } catch (SQLException e){
            e.printStackTrace();
        }finally {
            //关闭资源
            JDBCUtilsByDruid.close(set,preparedStatement,connection);
        }
        //因为ArrayList 和 connection 没有任何关联 所以该集合可以复用
        return list;
    }
}

六.Apache-DBUtils

基本介绍

  1. commons-dbutils 是Apache 组织提供的一个开源JDBC工具类,它是对JDBC的分装,使用dbutils能极大简化jdbc编程的工作量
  • DbUtils类
  • QueryRunner类:该类封装了sql的执行,是线程安全的。可以实现增,删,改,查,批处理 
  • 使用QueryRunner类实现查询
  • ResultHandler 接口:该接口用于处理 java.sql.ResultSet,将数据按照要求转换成为另外一种形式

ArrayHandler 把结果集中的第一行数据转换成对象数组

ArrayListHandler:把结果集中的每一行数据都转换成一个数组,在存放到List中

BeanHandler: 将结果集中的第一行数据分装到一个对应的JavaBean实例中

BeanListHandler :将结果集中的每一行数据分装到一个对应的JavaBean实例中,存放到List里

ColumnListHandler:将结果就中某一行的数据存放到List中

KeyedHandler(name) 将结果集中的每一行数据都分装到mvp里,在把这些map里,其key为指定的key

Maphandler:将结果集中的第一行数据分装到一个Map里面,key是列名,value就是对应的值

MapListHandler: 将结果集中的每一行数据都分装到一个Map里,然后在存放到List  

应用实例

使用DBUtils+ 数据连接池(德鲁伊)方式,完成对表actor的crud

package com.tianedu.jdbc.datasource;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;

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

/**
 * @author tian
 */
@SuppressWarnings({"all"})
public class DBUtils_USE {
    @Test
  //使用apache-DBUtils 工具类 + druid  的方式完成对表的crud操作
    public void testQueryMany() throws SQLException {   //返回结果是多行的情况

        //1. 得到连接
        Connection connection = JDBCUtilsByDruid.getConnection();
        //2.使用DBUtiles 类和接口  先引入德鲁伊的jar文件,加入到本project
        //3.创建一个 QueryRunner
        QueryRunner queryRunner = new QueryRunner();
        //4.就可以执行相关的方法,返回ArrayList 结果集
        //String  sql = "select * from actor where id >= ?";
        //注意 sql 语句也可以查询部分列
        String sql = "select id,name from actor where id >= ?";


        //1.query 方法就是执行一个sql语句得到一个resultset -- 分装到 --》 ArrayList 集合中然后返回
        //2.返回集合
        //3.connection: 连接
        //4.sql 执行sql语句
        //5.ew BeanListHandler<>(Actor.class)  再将resultset -》 actor 对象分装到 ArrayList
        //底层 使用反射机制 去获取actor 类的属性,然后进行封装
        //6. 1 是传递给sql 的? 的 可以有多个值,因为它是一个可变参数 Object... parames
        //7.底层 得到的resultSet 会在query 关闭,关闭PrepareStatment
        List<Actor> list =
                queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);
        System.out.println("输出集合的信息");
        for (Actor actor : list){
            System.out.print(actor);
        }
        // 释放资源
        JDBCUtilsByDruid.close(null,null,connection);
    }

}
package com.tianedu.jdbc.datasource;

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 org.junit.Test;

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

/**
 * @author tian
 */
@SuppressWarnings({"all"})
public class DBUtils_USE {
    @Test
  //使用apache-DBUtils 工具类 + druid  的方式完成对表的crud操作
    public void testQueryMany() throws SQLException {   //返回结果是多行的情况

        //1. 得到连接
        Connection connection = JDBCUtilsByDruid.getConnection();
        //2.使用DBUtiles 类和接口  先引入德鲁伊的jar文件,加入到本project
        //3.创建一个 QueryRunner
        QueryRunner queryRunner = new QueryRunner();
        //4.就可以执行相关的方法,返回ArrayList 结果集
        //String  sql = "select * from actor where id >= ?";
        //注意 sql 语句也可以查询部分列
        String sql = "select id,name from actor where id >= ?";


        //1.query 方法就是执行一个sql语句得到一个resultset -- 分装到 --》 ArrayList 集合中然后返回
        //2.返回集合
        //3.connection: 连接
        //4.sql 执行sql语句
        //5.ew BeanListHandler<>(Actor.class)  再将resultset -》 actor 对象分装到 ArrayList
        //底层 使用反射机制 去获取actor 类的属性,然后进行封装
        //6. 1 是传递给sql 的? 的 可以有多个值,因为它是一个可变参数 Object... parames
        //7.底层 得到的resultSet 会在query 关闭,关闭PrepareStatment
        List<Actor> list =
                queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);
        System.out.println("输出集合的信息");
        for (Actor actor : list){
            System.out.print(actor);
        }
        // 释放资源
        JDBCUtilsByDruid.close(null,null,connection);
    }
    // 演示 apache - dubtlis + druid 完成 返回的结果 是单行记录(单个对象)
    @Test
    public void testQuerySingle() throws SQLException {
        //1.得到连接
        Connection connection = JDBCUtilsByDruid.getConnection();
        //2.创建QueryRunner
        QueryRunner queryRunner = new QueryRunner();
        //3.sql 语句  执行相关方法,返回单个对象
        String sql = "select * from actor where id = ?";
        //因为我们知道返回的是单行记录  单个记录,使用Hander 是 BeanHandler
        Actor actor = queryRunner.query(connection, sql, new BeanHandler<>(Actor.class), 2);
        System.out.println(actor);
        JDBCUtilsByDruid.close(null,null,connection);

    }
    // 演示apache-dubtils + druid 完成查询结果是单行单列 - 返回的就是一个Object
    // Scalar 胆量
    @Test
    public void testScalar() throws SQLException {
        Connection connection = JDBCUtilsByDruid.getConnection();
        QueryRunner queryRunner = new QueryRunner();
        //执行相关方法,返回单行单列,返回的就是Obeject
        String sql = "select name from actor where id = ?";
        //因为返回的是单行单列,返回的是ScalarHandler
        Object obj= queryRunner.query(connection, sql, new ScalarHandler(), 2);
        System.out.println(obj);
        JDBCUtilsByDruid.close(null,null,connection);
    }

    //演示 apache-dbutils + druid 完成 dml(update insert delect)
    @Test
    public void testDML() throws SQLException {
        //得到连接
        Connection connection = JDBCUtilsByDruid.getConnection();
        //创建queryRunner
        QueryRunner queryRunner = new QueryRunner();

        //4.这里我们可以组织sql语句来完成 update insert delect
        //String sql = "update actor set name = ? where id = ?";



        //String sql = "insert into actor values(null,?,?,?,?)";

        String sql =" delete from actor where  id = ?";

        // 1.我们执行dml 操作使用 方法是 queryRunner.update()
        //2.返回值是受影响的行数 affectedRow 受影响的行

        //int affectedRow = queryRunner.update(connection, sql, "林青霞","女","1917-10-10","116");
        int affectedRow = queryRunner.update(connection,sql,100 );
        System.out.println(affectedRow > 0 ? "执行成功":"执行没有影响数据库·");
        //释放资源
        JDBCUtilsByDruid.close(null,null,connection);
    }
}

七.DAO 和增删改查 通用方法 - BasicDao

基本说明:

  • DAO: data access object 数据访问对象
  • 这样的通用类,称为BasicDao 是专门和数据库交互的,及完成对数据库(表)的crud操作
  • 在BaiscDao 的基础上,实现一张表 对应一个Dao 更好的完成功能,比如 Customer 表,Customer.java类(javabean)-CustomerDao.java

完成一个简单的设计

com.tianedu.dao_

  1. com.tainedu.dao_utils  //工具类
  2. com.tainedu.da0_.domain  //javabean
  3. com.tainedu.dao_.dao  //存放XXXDAO和BasicDAO
  4. com.tianedu.dao_.test //写测试类 
package com.tianedu.dao_.test;

import com.tianedu.dao_.dao.ActorDAO;
import com.tianedu.dao_.domain.Actor;
import org.junit.Test;

import java.util.List;

/**
 * @author tian
 */
public class TestDAO {
    @Test
    //测试ActorDAO 对 actor 表的crud操作
    public void testActorDAO() {
        ActorDAO actorDAO = new ActorDAO();
        //测试查询语句
        List<Actor> actors
                = actorDAO.queryMulti("select * from actor where id =?", Actor.class, 1);
        System.out.println("查询结果");
        for (Actor actor : actors) {
            System.out.println(actor);
        }
        //查询单行记录
        Actor actor = actorDAO.querySingle("select * from actor where id =?", Actor.class, 1);
        System.out.println(actor);
//查询单行单列
        Object o = actorDAO.queryScalar("select name from actor where id = ?", 1);
        System.out.println("==== 查询单行列值===");
        System.out.println(o);
        //演示dml操作
        int update =
                actorDAO.update("insert into actor values(null,?,?,?,?)", "张无忌", "男", "2000-11-11", "999");
        System.out.println(update > 0 ? "执行成功":"执行没有影响表");
    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1133772.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

民宿如何经营与管理?【民宿小程序】

随着旅游业的快速发展&#xff0c;越来越多的人选择经营民宿&#xff0c;将自己的房屋开放给旅客入住。然而&#xff0c;要成功经营一家民宿&#xff0c;并保持良好的运营状态&#xff0c;需要有效的管理和营销策略。在这个过程中&#xff0c;民宿小程序能够发挥重要作用。 民宿…

Python---练习:for循环 求1-100的和/所有偶数的和

案例&#xff1a; 使用for循环&#xff0c;求1 ~ 100的和 之前用while循环&#xff0c;做过算出1--100的和。 相关链接&#xff1a; Python--练习&#xff1a;使用while循环求1..100的和-CSDN博客 结合着看看for循环怎么实现。 思考&#xff1a; 先把for循环的基本语法写…

使用udevil自动挂载U盘或者USB移动硬盘

最近在折腾用树莓派&#xff08;实际上是平替香橙派orangepi zero3&#xff09;搭建共享文件服务器&#xff0c;有一个问题很重要&#xff0c;如何在系统启动时自动挂载USB移动硬盘。 1 使用/etc/fstab 最开始尝试了用/etc/fstab文件下增加:"/dev/sda1 /home/orangepi/s…

Unity 中忽略图片透明度的 Image 组件的修改版本

只需将此组件添加到画布中的空对象即可。请注意&#xff0c;仅支持简单 图像类型。 using System.Collections.Generic; using UnityEngine; using UnityEngine.Sprites; using UnityEngine.UI; #if UNITY_2017_4 || UNITY_2018_2_OR_NEWER using UnityEngine.U2D; #endif#if U…

分类预测 | MATLAB实现SSA-CNN-BiGRU-Attention数据分类预测(SE注意力机制)

分类预测 | MATLAB实现SSA-CNN-BiGRU-Attention数据分类预测&#xff08;SE注意力机制&#xff09; 目录 分类预测 | MATLAB实现SSA-CNN-BiGRU-Attention数据分类预测&#xff08;SE注意力机制&#xff09;分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.MATLA…

微信小程序如何跳转页面

1.wx.navigateTo&#xff1a;用于跳转到其他页面&#xff0c;并保留当前页面。通过该 API 跳转后&#xff0c;可以通过返回按钮回到原页面。 wx.navigateTo({url: /pages/otherPage/otherPage })2.wx.redirectTo&#xff1a;用于跳转到其他页面&#xff0c;并关闭当前页面。通…

上初三的小伙子做了个windows12网页版

某天逛GitHub突然刷到这个仓库&#xff0c;好奇的点了进去&#xff0c;读完md我懵了&#xff0c;作者才初三&#xff1f;wtf&#xff0c;现在内卷到这个程度了吗&#xff01;而且start还不低有5.2k。 效果展示 新的版本有很多变化&#xff0c;仅供参考&#xff0c;请以实物为准…

SpringBoot 自动配置@EnableAutoConfiguration

自动配置vs自动装配 Spring有两个名字听起来相似的概念&#xff1a;一个是自动装配&#xff0c;一个是自动配置。他们两个只是听起来相似&#xff0c;实际根本不同。自动装配是autowire&#xff0c;自动配置是autoconfiguration&#xff0c;他们之间没有任何关系&#xff0c;概…

ARM 版 OpenEuler 22.03 部署 KubeSphere v3.4.0 不完全指南

作者&#xff1a;运维有术 前言 知识点 定级&#xff1a;入门级KubeKey 安装部署 ARM 版 KubeSphere 和 KubernetesARM 版 KubeSphere 和 Kubernetes 常见问题 实战服务器配置 (个人云上测试服务器) 主机名IPCPU内存系统盘数据盘用途ks-master-1172.16.33.1661650200KubeSp…

翻页电子相册如何制作?看到就是赚到

在日常生活中&#xff0c;我们拿起手机随手一拍&#xff0c;即可记录美丽瞬间。但随着手机里的照片越来越多&#xff0c;这时该怎么办呢&#xff1f;相信很多小伙伴会选择把照片装订成相册&#xff0c;不过&#xff0c;时间一长也都成了压箱底&#xff0c;无人翻看。但除了这一…

sheng的学习笔记-【中】【吴恩达课后测验】Course 3 - 结构化机器学习项目 - 第一周测验

课程3_第1周_测验题 目录&#xff1a;目录 要解决的问题 ① 这个例子来源于实际项目&#xff0c;但是为了保护机密性&#xff0c;我们会对细节进行保护。 ② 现在你是和平之城的著名研究员&#xff0c;和平之城的人有一个共同的特点&#xff1a;他们害怕鸟类。 ③ 为了保护…

MyBatis-Plus 通过updateById更新日期null

date类型的字段为 一、需求&#xff1a; 有时候需要将页面日期重新赋值空&#xff0c;但是Mybatis Plus 默认情况下&#xff0c;baseMapper.updateById方法&#xff0c;当doman中字段值为null&#xff0c;后端并会不更新这个字段 解决方法&#xff1a; 对应的实体类的属性加…

浅谈智能制造

智能制造 如今&#xff0c;同一版本同一型号的手机&#xff0c;几乎是一模一样的。当我们说去选购商品&#xff0c;其实是在有限的型号中选择我们需要的那一款。可是&#xff0c;人的需求千变万化&#xff0c;为什么偏偏要归结到几个固定的型号上去呢&#xff1f;每个人不应该…

2023/10/25MySQL学习

外键约束 在子表添加外键后,不能在主表删除或更新记录,因为存在外键关联 删除外键,注意外键名称时我们添加外键时起的名称 使用cascade操作后,可以操作主表数据,并且子表的外键也会对应改变 set null的话,删除主表对应主键信息后,子表对应外键信息变为空 多表关系 创建中间表 可…

JavaScript进阶 第四天笔记——深浅拷贝、this绑定、防抖节流

JavaScript 进阶 - 第4天 深浅拷贝 浅拷贝 首先浅拷贝和深拷贝只针对引用类型 浅拷贝&#xff1a;拷贝的是地址 常见方法&#xff1a; 拷贝对象&#xff1a;Object.assgin() / 展开运算符 {…obj} 拷贝对象拷贝数组&#xff1a;Array.prototype.concat() 或者 […arr] 如…

NSSCTF做题第9页(3)

[GKCTF 2020]CheckIN 代码审计 这段代码定义了一个名为ClassName的类&#xff0c;并在脚本的最后创建了一个ClassName类的实例。 在ClassName类的构造函数中&#xff0c;首先通过调用$this->x()方法获取了请求参数$_REQUEST中的值&#xff0c;并将其赋值给$this->code属性…

Android [SPI,AutoSerivce,ServiceLoader]

记录一下在Android中使用SPI的过程。 1.项目gralde文件。 plugins {id kotlin-kapt } dependencies {implementation com.google.auto.service:auto-service:1.0-rc7 kapt "com.google.auto.service:auto-service:1.0-rc7" } 这个AutoServ…

【Qt】绘图与绘图设备

文章目录 绘图设备QPainter绘图实例案例1案例2-高级设置案例3&#xff1a;利用画家画资源图片 点击按钮移动图片 QtPaintDevice实例Pixmap绘图设备QImage 绘图设备QPicture 绘图设备 QPainter绘图 Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系…

外卖跑腿小程序开发如何满足不断变化的用户需求?

外卖跑腿小程序市场竞争激烈&#xff0c;用户需求不断演变。为了保持竞争力&#xff0c;开发团队需要不断适应变化&#xff0c;提供新功能和改进用户体验。本文将讨论如何通过技术手段来满足不断变化的用户需求。 1. 灵活的后端服务 后端服务是外卖跑腿小程序的核心&#xf…

Sui主网升级至V1.12.2版本

其他升级要点如下所示&#xff1a; #14305 使Sui能够验证zkLogin历史地址&#xff08;通过已填充的address_seed派生&#xff09;。升级协议版本至29&#xff0c;以启用对历史地址的验证。 #14100 修复了verify_zklogin_id函数中的错误&#xff0c;该函数按预期返回一个Ver…