JDBC的演进

前序

JDBC是什么?

  • Java DataBase Connectivity(Java语言连接数据库)

  • JDBC是SUN公司制定的一套接口(interface)
    java.sql.*;(这个软件包下有很多接口)

  • 接口都有调用者和实现者。

  • 面向接口调用、面向接口写实现类,这都属于面向接口编程

为什么要面向接口编程?

解耦:降低程序间的耦合度,提高程序的扩展力;如多态

JDBC中重要的类与接口

  1. DriverManager:依据数据库的不同,管理JDBC驱动
  2. Connection:负责连接数据库并担任传送数据库的任务
  3. Statement:由Connection产生、负责执行SQL语句
  4. PrepareStatement:预编译的SQL语句)提高了SQL语句的性能、代码的安全性、代码的可读性和可维护性
  5. ResultSet:负责保存Statement执行后所产生的查询结果

PreparedStatement比Statement提高了代码的可读性和可维护性,提高了SQL语句执行的性能,提高了安全性

JDBC实现步骤

在这里插入图片描述

1.导入数据库的驱动程序。
2.创建连按字符串。
3.注册驱动。
4.创建连按对象。
5.创建命令语句执行对象。
6.执行SQL操作井返回结果集对象。
7.对结果集进行处理。
8.释放资源,关闭连接。

使用的类

 <dependencies>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1.1</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.1.2</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.22</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
    <dependency>
      <groupId>org.dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>2.0.0</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
  </dependencies>

JDBC1.0 原始

最原始的连接:

  1. 数据库的连接创建、释放频繁造成系统资源浪费从而影响系统性能
  2. sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化需要改动java代码
  3. 查询操作时,需要手动将结果集中的数据手动封装到实体中。插入操作时,需要手动将实体的数据设置到sql语句的占位符位置
  4. 每一次数据库连接,使用完后都要断开,假如程序出现异常而没能关闭,将会导致数据库内存)泄漏,将导致重启数据库。
public class JDBCDemo1 {
    //你要操作的数据库是哪种类型
    static String driver = "com.mysql.cj.jdbc.Driver";
    //表示你操作的数据库安装在哪个位置端口数据库名称
    static String url = "jdbc:mysql://localhost:3306/javatest?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true";
    //登录数据库服务器的用户
    static String username = "root";
    //登录数据库服务器的用户的密码
    static String password = "123456";
    static Connection connection = null;
    static Statement statement = null;
    static ResultSet resultSet = null;

    public static void main(String[] args) {
        fun1();
    }

    private static void fun1() {
        try {
            // 加载驱动
            Class.forName(driver);
            // 创建连接对象
            connection = DriverManager.getConnection(url, username, password);
            System.out.println(connection);
            // 创建命令语句执行对象
            Statement statement = connection.createStatement();
            // sql语句
            String sql = "select * from users";
            // 执行命令语句,返回结果集
            resultSet = statement.executeQuery(sql);
            // 判断结果集是否有下一行;next是一个回调函数
            while (resultSet.next()) {
                System.out.println(resultSet.getObject(1) + "\t" + resultSet.getObject(2));
            }
            System.out.println(resultSet);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("注册数据库驱动异常!" + e);
        } catch (SQLException e2) {
            throw new RuntimeException("创建连接对象发生异常!" + e2);
        } finally {
            // 某个阶段可能发生异常的时候,会影响到后面资源的释放,所以每个资源的关闭都是独立的
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException("resultSet关闭时发生异常!");
            }
            try {
                if (statement != null) {
                    statement.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException("statement关闭时发生异常!");
            }
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException("connection关闭时发生异常!");
            }
        }
    }

}

JDBC2.0 properties

对于jdbc1.0实现解耦:

  1. 解决硬编码
  2. 释放资源

db.properties

  • 开发中获得连接的4个参数(驱动、URL、用户名、密码)通常都存在配置文件中,方便后期维护,程序如果需要更换数据库,只需要修改配置文件即可

  • 配置文件用来保存一些在程序中可能修改的值,修改时只要修改配置文件即可,而不用修改程序本身

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/javatest?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
username=root
password=123456

IO流读取配置

  • 1.通过IO读取文件
  • 2.创建Properties对象
  • 3.使用Properties对象的load(流)方法加载数据
  • 4.使用Properties对象的getProperty(键)方法获取对应值
public class JDBCUtils {

    static Connection connection=null;
    static Statement statement=null;
    static ResultSet resultSet=null;
    static String driver;
    static String url;
    static String username;
    static String password;
    static{
        //读取配置文件获得连接信息
        // getContextClassLoader 表示获取此线程运行的工程上下文
        // getResourceAsStream 在上下文规定目录中获取指定文件
        InputStream input = Thread.currentThread().
                getContextClassLoader().
                getResourceAsStream("db.properties");
        Properties properties=new Properties();
        try {
            // 加载配置文件中的数据
             properties.load(input);
             driver = properties.getProperty("driver");
             url = properties.getProperty("url");
             username = properties.getProperty("username");
             password = properties.getProperty("password");
        } catch (IOException e) {
            throw new RuntimeException("Properties加载失败!");
        }


    }

    /**
     * 创建连接对象并返回
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static Connection createConnection() throws ClassNotFoundException, SQLException {
        Class.forName(driver);
        return DriverManager.
                getConnection(url, username, password);
    }

    /**
     * 关闭连接释放资源
     * 先打开的后关闭
     * 后打开的先关闭
     * @param connection
     * @param statement
     * @param resultSet
     */
    public static void release(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("resultSet关闭时发生异常!");
        }
        try {
            if (statement != null) {
                statement.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("statement关闭时发生异常!");
        }
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("connection关闭时发生异常!");
        }
    }
}

使用

public class JDBCDemo2  {
    static Connection connection=null;
    static Statement statement=null;
    static ResultSet resultSet=null;
    public static void main(String[] args) {
        fun1();
    }
    private static void fun1() {
        try {
            connection=JDBCUtils4.createConnection();
            if(connection!=null){
                statement = connection.createStatement();
                String sql="select * from users";
                resultSet = statement.executeQuery(sql);
                while (resultSet.next()){
                    System.out.println(resultSet.getObject(1)+"\t"+resultSet.getObject(2));
                }
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("注册数据库驱动异常!"+e);
        } catch (SQLException e2) {
            throw new RuntimeException("创建连接对象发生异常!"+e2);
        }finally {
            JDBCUtils4.release(connection,statement,resultSet);
        }
    }
}

JDBC3.0 XML

db.xml

<?xml version="1.0" encoding="UTF-8"?>
<ZDY>
    <driver>com.mysql.cj.jdbc.Driver</driver>
    <url>jdbc:mysql://localhost:3306/javaTest?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;nullCatalogMeansCurrent=true&amp;useSSL=false</url>
    <username>root</username>
    <password>123456</password>
</ZDY>

dom4j读取配置

dom4j是一个Java的XML API,是jdom的升级版。用于读写xml文件

package com.pursue.JDBCFile;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

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

/**
 * 操作jdbc的工具类:
 * 负责:
 * 一个是创建连接
 * 二个是释放资源
 * 问题:
 * 有一些配置文件是使用xml来保存的,能不能读?
 * 注意:
 * dom4j是一个Java的XML API,是jdom的升级品,
 * 用来读写XML文件的。
 */
public class JDBCUtils3 {

    static Connection connection = null;
    static Statement statement = null;
    static ResultSet resultSet = null;
    static String driver;
    static String url;
    static String username;
    static String password;

    static {
        SAXReader saxReader = new SAXReader();
        try {
            // xml字符串 解析为Document对象
            Document read = saxReader.read("src/main/resources/db.xml");
            // 获取文档根节点  : 获取文档中最高一级的标签
            Element rootElement = read.getRootElement();
            System.err.println(rootElement + " --- ");
            driver = rootElement.element("driver").getText();
            // 获取根节点下面的指定节点
            url = rootElement.element("url").getText();
            username = rootElement.element("username").getText();
            password = rootElement.element("password").getText();

        } catch (DocumentException e) {
            throw new RuntimeException("读取xml文件异常");
        }
    }

    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        System.out.println(createConnection());
    }

    /**
     * 创建连接对象并返回
     *
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static Connection createConnection() throws ClassNotFoundException, SQLException {
        Class.forName(driver);
        return DriverManager.
                getConnection(url, username, password);
    }

    /**
     * 关闭连接释放资源
     * 先打开的后关闭
     * 后打开的先关闭
     *
     * @param connection
     * @param statement
     * @param resultSet
     */
    public static void release(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("resultSet关闭时发生异常!");
        }
        try {
            if (statement != null) {
                statement.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("statement关闭时发生异常!");
        }
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("connection关闭时发生异常!");
        }
    }
}

在这里插入图片描述

使用

  1. SQL命令问题
  2. 参数变量的形式传入应更合理灵活
  3. SQL参数可有可无,类型不确定
  4. SQL注入攻击 注入攻击:ddxxx’or’1=1

解决:使用Statement的子接口:PreparedStatement

public class JDBCDemo3 {
    static Connection connection=null;
    static Statement statement=null;
    static ResultSet resultSet=null;
    static PreparedStatement pt=null;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户的id");
        int id=scanner.nextInt();
        System.out.println("请输入用户的姓名");
        String uname=scanner.next();
        //String sql="select * from users where uname='"+uname+"'";
        String sql="select * from users where uid=? and uname=?";
        fun1(sql,new Object[]{id,uname});

    }
    // Object...objects:可变长参数
    // 只能放在参数列表的最后一个位置上,而且可变长度参数只能有1个
    // 可变长度参数,可以当做一个数组来看待
    private static void fun1(String sql, Object...objects) {
        try {
            connection=JDBCUtils4.createConnection();
            if(connection!=null){
                /*statement = connection.createStatement();
                resultSet = statement.executeQuery(sql);*/
                //预编译
                pt=connection.prepareStatement(sql);
                bangding(objects);
                resultSet=pt.executeQuery();
                while (resultSet.next()){
                    System.out.println(resultSet.getObject(1)+"\t"+resultSet.getObject(2));
                }
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("注册数据库驱动异常!"+e);
        } catch (SQLException e2) {
            throw new RuntimeException("创建连接对象发生异常!"+e2);
        }finally {
            JDBCUtils4.release(connection,statement,resultSet);
        }
    }

    /**
     * 绑定参数
     * @param objects
     */
    private static void bangding(Object[] objects) {
        try{
            if(objects!=null && objects.length>0){
                for (int i = 0; i < objects.length; i++) {
                    pt.setObject(i+1, objects[i]);
                }
            }
        }catch (Exception e){
            throw new RuntimeException("参数绑定异常!"+e);
        }

    }
}

分界线

后续案例使用C3P0,详情JDBC5.0

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 这是默认配置信息 -->
    <default-config>
        <!-- 连接四大参数配置 -->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/javaTest?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;nullCatalogMeansCurrent=true&amp;useSSL=false</property>
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <!--配置数据库连接池的初始连接数、最小链接数、获取连接数、最大连接数、最大空闲时间-->
        <property name="initialPoolSize">5</property>
        <property name="minPoolSize">2</property>
        <property name="acquireIncrement">3</property>
        <property name="maxPoolSize">5</property>
        <property name="maxIdleTime">30</property>
    </default-config>
</c3p0-config>
package com.pursue.JDBCFile;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.*;
/**
 *  操作jdbc的工具类:
 *  负责:
 *     一个是创建连接
 *     二个是释放资源
 *  问题:
 *      数据库的连接对象创建和销毁太过频繁,不稳定。
 *  注意:
 *      可以考虑使用连接池技术来解决
 *      C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,
 *      支持JDBC3规范和JDBC2的标准扩展。
 *      使用它的开源项目有Hibernate、Spring等。
 */
public class JDBCUtils4 {
    /**
     * 创建连接对象并返回
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static Connection createConnection() throws ClassNotFoundException, SQLException {
        ComboPooledDataSource dataSource=new ComboPooledDataSource("c3p0-config.xml");
        return dataSource.getConnection();
    }

    /**
     * 关闭连接释放资源
     * 先打开的后关闭
     * 后打开的先关闭
     * @param connection
     * @param statement
     * @param resultSet
     */
    public static void release(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("resultSet关闭时发生异常!");
        }
        try {
            if (statement != null) {
                statement.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("statement关闭时发生异常!");
        }
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("connection关闭时发生异常!");
        }
    }
}

JDBC4.0 结果集

反射加泛型 封装结果集

package com.pursue.JDBCFile;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * 问题一:结果集不需要输出,可以存储到集合中返回
 * 我怎么知道我查询的数据有多少条,每一条有多少个字段呢?
 * 我又怎么知道封装成哪种对象呢?
 * 问题二:我要封装的是哪处对象呢?
 * 解决:使用反射加泛型集合搞定了
 */
public class JDBCDemo4<T> {
    static Connection connection = null;
    static Statement statement = null;
    static ResultSet resultSet = null;
    static PreparedStatement pt = null;
    private Class cs;

    public JDBCDemo4() {

    }

    public JDBCDemo4(Class cs) {
        this.cs = cs;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户的id");
        int id = scanner.nextInt();
        System.out.println("请输入用户的姓名");
        String uname = scanner.next();
        String sql = "select * from users where uid=? and uname=?";
        JDBCDemo4 demo4 = new JDBCDemo4(Users.class);
        List<Users> list = demo4.fun1(sql, new Object[]{id, uname});
        for (Users users : list) {
            System.out.println(users);
        }

    }

    private List<T> fun1(String sql, Object... objects) {
        List<T> list = new ArrayList();
        try {
            connection = JDBCUtils4.createConnection();
            if (connection != null) {
                //预编译
                pt = connection.prepareStatement(sql);
                bangding(objects);
                resultSet = pt.executeQuery();
                while (resultSet.next()) {
                    //从结果集中封装对象并存储到集合中
                    list.add(encapsulations());
                }
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("注册数据库驱动异常!" + e);
        } catch (SQLException e2) {
            throw new RuntimeException("创建连接对象发生异常!" + e2);
        } finally {
            JDBCUtils4.release(connection, statement, resultSet);
        }
        return list;
    }

    /**
     * 从结果集中封装实体类
     *
     * @return
     */
    private T encapsulations() {
        T t = null;
        try {
            // 创建对象
            t = (T) cs.newInstance();
            // 获取全部属性信息
            Field[] ds = cs.getDeclaredFields();
            for (Field field : ds) {
                // 启用和禁用访问安全检查的开关:设置为可访问私有成员变量
                field.setAccessible(true);
                // 获取此ResultSet对象当前行中指定列的值作为object
                //此方法将以Java对象的形式返回给定列的值
                Object value = resultSet.getObject(field.getName());
                //把t对象的field字段填充为value的值
                field.set(t, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 绑定参数
     *
     * @param objects
     */
    private static void bangding(Object[] objects) {
        try {
            if (objects != null && objects.length > 0) {
                for (int i = 0; i < objects.length; i++) {
                    pt.setObject(i + 1, objects[i]);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("参数绑定异常!" + e);
        }
    }
}

JDBC5.0 c3p0

转载于:https://www.cnblogs.com/SUN99bk/p/12181493.html#_label4_2

解决:传统开发模式创建连接导致的一系列问题

  1. 时间和内存消耗大
    1. 普通的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将Connection加载到内存中,再根据JDBC代码(或配置文件)中的用户名和密码进行验证其正确性
    2. 一旦需要数据库连接的时候就必须向数据库请求一个,执行完后再断开连接。显然,如果同一个数据库在同一时间有数十人甚至上百人请求连接势必会占用大量的系统资源,严重的会导致服务器崩溃
  2. 有内存泄漏的风险
    1. 每一次数据库连接使用完后都需要断开连接,但如果程序出现异常致使连接未能及时关闭,这样就可能导致内存泄漏,最终只能以重启数据库的方法来解决;
    2. 使用传统JDBC模式开发不能控制需要创建的连接数,系统一般会将资源大量分出给连接以防止资源不够用,如果连接数超出一定数量也会有极大的可能导致内存泄漏。

数据库连接池技术

数据库连接池的基本原理就是为数据库建立一个缓冲池

  1. 资源的高效利用
    1. 自动回收空闲连接(连接重用),避免了频繁的创建,释放连接引起的大量性能开销,减小了系统资源消耗的同时也提高了系统运行环境的平稳性
  2. 更快的系统反应速度
    1. 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接可以避免数据库在连接初始化和释放过程所需的时间开销,从而减少了系统的响应时间,提高了系统的反应速度。
  3. 减少了资源独占的风险
    1. 新的资源分配手段对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置实现对某一应用最大可用数据库连接数的限制,避免了应用独占所有数据库资源的风险。
  4. 统一的连接管理,避免数据库连接泄露
    1. 在实现较为完善的数据库连接池时,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。

c3p0-config

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI【访问命名和目录服务的API】绑定,支持JDBC3规范和JDBC2的标准扩展。使用它的开源项目有Hibernate、Spring等

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 这是默认配置信息 -->
    <default-config>
        <!-- 连接四大参数配置 -->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/javaTest?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;nullCatalogMeansCurrent=true&amp;useSSL=false</property>
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <!--配置数据库连接池的初始连接数、最小链接数、获取连接数、最大连接数、最大空闲时间-->
        <property name="initialPoolSize">5</property>
        <property name="minPoolSize">2</property>
        <property name="acquireIncrement">3</property>
        <property name="maxPoolSize">5</property>
        <property name="maxIdleTime">30</property>
    </default-config>
</c3p0-config>

读取

public class JDBCUtils4 {
    /**
     * 创建连接对象并返回
     * @return
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static Connection createConnection() throws ClassNotFoundException, SQLException {
        ComboPooledDataSource dataSource=new ComboPooledDataSource("c3p0-config.xml");
        return dataSource.getConnection();
    }

    /**
     * 关闭连接释放资源
     * 先打开的后关闭
     * 后打开的先关闭
     * @param connection
     * @param statement
     * @param resultSet
     */
    public static void release(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("resultSet关闭时发生异常!");
        }
        try {
            if (statement != null) {
                statement.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("statement关闭时发生异常!");
        }
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException("connection关闭时发生异常!");
        }
    }
}

使用

客户说:返回的数据不需要返回实体类,只需要返回JSON格式即可

public class JDBCDemo5<T> {
    static Connection connection = null;
    static ResultSet resultSet = null;
    static PreparedStatement pt = null;
    /**
     * 由用户控制返回的类
     */
    private Class cs;

    public JDBCDemo5() {

    }

    public JDBCDemo5(Class cs) {
        this.cs = cs;
    }

    public static void main(String[] args) {
        String sql = "select * from users ";
        JDBCDemo5 demo5 = new JDBCDemo5(Users.class);
        Map<Object, Map<Object, Object>> map = demo5.fun1(sql);
        Set<Map.Entry<Object, Map<Object, Object>>> entries = map.entrySet();
        for (Map.Entry<Object, Map<Object, Object>> entry : entries) {
            System.out.println("用户的编号是:" + entry.getKey());
            System.out.println("用户的信息是:" + entry.getValue());
        }
    }

    private Map<Object, Map<Object, Object>> fun1(String sql, Object... objects) {
        Map<Object, Map<Object, Object>> maxmap = new LinkedHashMap<>();
        try {
            connection = JDBCUtils4.createConnection();
            if (connection != null) {
                //预编译
                pt = connection.prepareStatement(sql);
                bangding(objects);
                resultSet = pt.executeQuery();
                // 此resultset对象列的描述
                ResultSetMetaData metaData = resultSet.getMetaData();
                while (resultSet.next()) {
                    Map<Object, Object> minmap = new LinkedHashMap<>();
                    // getColumnCount 列数
                    for (int i = 1; i <= metaData.getColumnCount(); i++) {
                        // getColumnName 列名
                        minmap.put(metaData.getColumnName(i), resultSet.getObject(i));
                    }
                    // 由列变行
                    maxmap.put(resultSet.getObject(1), minmap);
                }
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("注册数据库驱动异常!" + e);
        } catch (SQLException e2) {
            throw new RuntimeException("创建连接对象发生异常!" + e2);
        } finally {
            JDBCUtils4.release(connection, pt, resultSet);
        }
        return maxmap;
    }


    /**
     * 绑定参数
     *
     * @param objects
     */
    private static void bangding(Object[] objects) {
        try {
            if (objects != null && objects.length > 0) {
                for (int i = 0; i < objects.length; i++) {
                    pt.setObject(i + 1, objects[i]);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("参数绑定异常!" + e);
        }
    }
}

JDBC6.0 新增

public class JDBCDemo6<T> {
    static Connection connection = null;
    static Statement statement = null;
    static ResultSet resultSet = null;
    static PreparedStatement pt = null;

    public static void main(String[] args) {
        System.out.println("请输入第一次要新增的学号:");
        int uid = new Scanner(System.in).nextInt();
        System.out.println("请输入第一次要新增的姓名:");
        String uname = new Scanner(System.in).next();
        String sql = "insert into users values (?,?)";
        JDBCDemo6 demo6 = new JDBCDemo6();
        int num = demo6.fun1(sql, new Object[]{uid, uname});
        if (num > 0) {
            System.out.println("新增成功!");
        } else {
            System.out.println("新增失败!");
        }

    }

    private int fun1(String sql, Object... objects) {
        try {
            connection = JDBCUtils4.createConnection();
            if (connection != null) {
                //预编译
                pt = connection.prepareStatement(sql);
                bangding(objects);
                return pt.executeUpdate();
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("注册数据库驱动异常!" + e);
        } catch (SQLException e2) {
            throw new RuntimeException("创建连接对象发生异常!" + e2);
        } finally {
            JDBCUtils4.release(connection, pt, resultSet);
        }
        return 0;
    }


    /**
     * 绑定参数
     *
     * @param objects
     */
    private static void bangding(Object[] objects) {
        try {
            if (objects != null && objects.length > 0) {
                for (int i = 0; i < objects.length; i++) {
                    pt.setObject(i + 1, objects[i]);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("参数绑定异常!" + e);
        }
    }
}

JDBC7.0 批量新增

public class JDBCDemo7<T> {
    static Connection connection = null;
    static Statement statement = null;
    static ResultSet resultSet = null;
    static PreparedStatement pt = null;

    public static void main(String[] args) {
        System.out.println("请输入第一次要新增的学号:");
        int uid = new Scanner(System.in).nextInt();
        System.out.println("请输入第一次要新增的姓名:");
        String uname = new Scanner(System.in).next();

        System.out.println("请输入第二次要新增的学号:");
        int uid2 = new Scanner(System.in).nextInt();
        System.out.println("请输入第二次要新增的姓名:");

        String uname2 = new Scanner(System.in).next();
        String sql = "insert into users values (?,?)";
        JDBCDemo7 demo6 = new JDBCDemo7();

        List<List> list = new ArrayList();
        List list1 = new ArrayList();
        list1.add(uid);
        list1.add(uname);

        List list2 = new ArrayList();
        list2.add(uid2);
        list2.add(uname2);

        list.add(list1);
        list.add(list2);
        int[] ints = demo6.fun1(sql, list);
        // 影响行数
        System.out.println(ints.length);
    }

    private int[] fun1(String sql, List<List> list) {
        int[] num = null;
        try {
            connection = JDBCUtils4.createConnection();
            if (connection != null) {
                //预编译
                pt = connection.prepareStatement(sql);
                for (List list1 : list) {
                    //表示参数绑定
                    bangding(list1.toArray());
                    // 将一组参数添加到此PreparedStatement对象的批命令中
                    pt.addBatch();
                }
                //批处理所有的sql命令
                num = pt.executeBatch();
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("注册数据库驱动异常!" + e);
        } catch (SQLException e2) {
            throw new RuntimeException("创建连接对象发生异常!" + e2);
        } finally {
            JDBCUtils4.release(connection, pt, resultSet);
        }
        return num;
    }


    /**
     * 绑定参数
     *
     * @param objects
     */
    private static void bangding(Object[] objects) {
        try {
            if (objects != null && objects.length > 0) {
                for (int i = 0; i < objects.length; i++) {
                    pt.setObject(i + 1, objects[i]);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("参数绑定异常!" + e);
        }
    }
}

JDBC8.0 事务

  1. 数据库系统保证在一个事务中的所有SQL要么全部执行成功,要么全部不执行
  2. JDBC中执行事务,本质上就是如何把多条SQL包裹在一个数据库事务中执行
  3. 对应用程序来说,数据库事务非常重要,很多运行着关键任务的应用程序,都必须依赖数据库事务保证程序的结果正常
public class JDBCDemo8<T>{
    static Connection connection=null;
    static Statement statement=null;
    static ResultSet resultSet=null;
    static PreparedStatement pt=null;
    private Class cs;
    public JDBCDemo8(){

    }
    public JDBCDemo8(Class cs){
        this.cs=cs;
    }
    public static void main(String[] args) {
        System.out.println("请输入第一次要新增的学号:");
        int uid=new Scanner(System.in).nextInt();
        System.out.println("请输入第一次要新增的姓名:");
        String uname=new Scanner(System.in).next();

        System.out.println("请输入第二次要新增的学号:");
        int uid2=new Scanner(System.in).nextInt();
        System.out.println("请输入第二次要新增的姓名:");
        String uname2=new Scanner(System.in).next();
        String sql="insert into users values (?,?)";
        JDBCDemo8 demo6=new JDBCDemo8();

        List<List> list=new ArrayList();
        List list1=new ArrayList();
        list1.add(uid);
        list1.add(uname);

        List list2=new ArrayList();
        list2.add(uid2);
        list2.add(uname2);

        list.add(list1);
        list.add(list2);
        int[] ints = demo6.fun1(sql, list);
        System.out.println(ints.length);


    }

    /**
     * 带事务功能的批处理
     * @param sql
     * @param list
     * @return
     */
    private int[] fun1(String sql,List<List> list) {
        int [] num=null;
        try {
            connection=JDBCUtils4.createConnection();
            //关闭数据库的自动提交功能:打开事务监控
            connection.setAutoCommit(false);
            if(connection!=null){
                //预编译
                pt=connection.prepareStatement(sql);
                for (List list1 : list) {
                    //表示参数绑定
                    bangding(list1.toArray());
                    //保存一条完整的sql命令
                    pt.addBatch();
                }
                //批处理所有的sql命令
                num=pt.executeBatch();
                //提交事务:相当于事务的关闭
                connection.commit();
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("注册数据库驱动异常!"+e);
        } catch (SQLException e2) {
            throw new RuntimeException("创建连接对象发生异常!"+e2);
        }finally {
            try {
                //事务回滚
                connection.rollback();
            } catch (SQLException e) {
                throw new RuntimeException("数据回滚失败!");
            }
            JDBCUtils4.release(connection,pt,resultSet);
        }
        return num;
    }



    /**
     * 绑定参数
     * @param objects
     */
    private static void bangding(Object[] objects) {
        try{
            if(objects!=null && objects.length>0){
                for (int i = 0; i < objects.length; i++) {
                    pt.setObject(i+1, objects[i]);
                }
            }
        }catch (Exception e){
            throw new RuntimeException("参数绑定异常!"+e);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值