吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2134|回复: 15
收起左侧

[学习记录] 【自学笔记】 Java基础 - JDBC

[复制链接]
LongJL 发表于 2021-7-24 11:19

JDBC基础

阅读这篇笔记你需要掌握反射和Mysql这些知识。

概念

JDBC ( Java DataBase Connectivity java数据库连接)是-种用于执行SQL语句的JavaAPI ,可以为多种关系型数据库提供统一访问,它是由一组用Java语言编写的类和接口组成的。其实就是java官方提供的一套规范(接口),用于帮助开发人员快速实现不同关系型数据库的连接。

快速入门

  • 导入jar包
  • 注册驱动
  • 获取数据库连接
  • 获取执行者对象
  • 执行sql语句并返回结果
  • 处理结果
  • 释放资源
public class JDBCDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
//        -导入jar包
//        - 注册驱动
        Class.forName("com.mysql.jdbc.Driver");
//        - 获取数据库连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/qq", "root", "root");
//        - 获取执行者对象
        Statement statement = connection.createStatement();
//        - 执行sql语句并返回结果
        String sql = "SELECT * FROM user";
        ResultSet resultSet = statement.executeQuery(sql);
//        - 处理结果
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");

            System.out.print(id + "  ");
            System.out.println(username);
        }
//        - 释放资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

功能类解释

DriverManager

DriverManager取得管理对象

  1. 注册驱动

    • 注册给定的驱动程序:static void registerDriver(Driver driver)
    • 写代码使用:Class.forName("com.mysql.jdbc.Driver")
    • com.mysqlJdbc.Driver类中存在静态代码块,里面就已经实现注册驱动
      static {
      try {
      DriverManager.registerDriver(new Driver());
      } catch (SQLException var1) {
      throw new RuntimeException("Can't register driver!");
      }
      }
    • 注意事项
      1. 我们不需要提供DriverManager调用静态方法registerDriver(),以为只要Driver类被使用,则会执行其静态代码块完成驱动注册
      2. mysql5之后可以省略注册驱动步骤。在jar包中,存在一个java.sql.Driver配置文件,文件中指定了com.mysql.jdbc.Driver
  2. 获取数据库连接
    获取数据库连接对象:static Connection getConnection(String url,String user,String password)
    参数:
    url:指定连接的路径。语法:"jdbc:mysql://ip地址(域名):端口号/数据库名称"
    user:用户名
    password:密码
    返回值:Connection数据库连接对象

Connection

Connection数据库连接对象

  1. 获取执行者对象
    获取普通执行者对象:Statement createStatement();
    获取预编译执行者对象:PreparedStatement prepareStatement(Sting sql);

  2. 管理事务
    开启事务:setAutoCommit(boolean autoCommit);参数为false,则开启事务
    提交事务:commit();
    回滚事务:rollback();

  3. 释放资源
    void close()

Statement

Statement执行sql语句对象

  1. 执行DML(增删改)语句
    int executeUpdate(String sql)
    返回值int,返回影响的行数
    参数sql:可以执行insert、update、delete语句
    2.执行DQL语句
    ResultSet executeQuery(String sql)
    返回值ResultSet:封装查询结果
    参数sql:可以执行select语句
    3.释放资源
    void close()

ResultSet

ResultSet结果集对象

  1. 判断结果集当作是否还要数据boolean next();
    有数据返回true,并将索引向下移动一行
    没有数据返回false

2.获取结果集中的数据:XXX getXXX("列名")
xxx代表数据类型(要获取某列数据,这一列的数据类型)
例如:String getString("name); int getInt("age")
3.释放资源
void close()

工具类

  1. 编写配置文件,在src目录下创建config.properties配置文件
    config.properties:
    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/qq
    username=root
    password=root

2.编写jdbc工具类

public class JDBCUtils {

    // 1.私有化构造方法
    private JDBCUtils(){

    }

    // 2.声明所需要的配置变量
    private static String driverClass;
    private static String url;
    private static String username;
    private static String password;
    private static Connection con;

    // 3.提供静态代码块,读取配置文件的信息为变量赋值,注册驱动
    static {
        // 读取配置文件的信息为变量赋值
        try {
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");
            Properties properties = new Properties();
            properties.load(is);
            driverClass= properties.getProperty("driverClass");
            url= properties.getProperty("url");
            username= properties.getProperty("username");
            password= properties.getProperty("password");

            // 注册驱动
            Class.forName(driverClass);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 4.提供获取数据库连接方法
    public static Connection getConnection(){
        try {
            con = DriverManager.getConnection(url,username,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return con;
    }

    // 5.提供释放资源的方法
    public static void close(Connection con, Statement stat, ResultSet rs){
        if (con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

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

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

    // 5.提供释放资源的方法
    public static void close(Connection con, Statement stat){
        if (con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

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

    }
}

SQL注入攻击解决

  • PreparedStatement预编译执行者对象
    1. SQL语句之前,将SQL语句进行提取编译。明确SQL语句的格式后,就不会在改变,剩余的内容都会认为时参数。
    2. SQL语句中的参数使用?占位符
  • 为?占位符赋值的方法:setXxx(参数1,参数2)
    Xxx:数据类型
    参数1:?的位置编号(编号从1开始)
    参数2:?的实际参数
        string sq1 = "DELETE FROM user WHERE name=?"
        pstm = conn.preparestatement(sq1) ; 
        pstm. setstring(1,"张三");
  • 执行SQL语句
    1. 执行inset、update、delete语句:int executeUpdate();
    2. 执行select语句:ResultSet executeQuery();
public class JDBCDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
//        -导入jar包
//        - 注册驱动
//        Class.forName("com.mysql.jdbc.Driver");
//        - 获取数据库连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/qq", "root", "root");
//        - 获取执行者对象

//        - 执行sql语句并返回结果
        String sql = "SELECT * FROM user WHERE name = ?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1,"张三");
        ResultSet resultSet = preparedStatement.executeQuery(sql);
//        - 处理结果
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");

            System.out.print(id + "  ");
            System.out.println(username);
        }
//        - 释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

事务管理

管理事务功能类:Connection

  • 开启事务:`setAutoCommit(boolean autoCommit):参数为false,则开始事务
  • 提交事务:commit();
  • 回滚事务:rollback();

连接池

概念

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。可以有效的提升数据库操作的性能

自定义数据库连接池

DataSource
概述

Javax.sql.DataSource接口:数据源(数据库连接池)。Java官方提供的数据库连接池规范(接口)

步骤
① 定义一一个类,实现DataSource接口。
② 定义一个容器,用于保存多个Connection连接对象。
③ 定义静态代码块,通过JDBC工具类获取10个连接保存到容器中。
④ 重写getConnection方法,从容器中获取一个连接并返回。
⑤ 定义getSize方法,用于获取容器的大小并返回。
/**
 * 自定义数据库连接池
 */

public class MyDataSource implements DataSource {
    // 准备容器,用于保存多个连接对象
    // 通过Collections.synchronizedList获取线程安全的集合对象
    private static List<Connection> pool = Collections.synchronizedList(new ArrayList<>());

    // 定义静态代码块,通过工具类获取10个连接对象
    static {
        for (int i = 0; i < 10; i++) {
            Connection connection = JDBCUtils.getConnection();
            pool.add(connection);
        }
    }

    // 重写getConnection方法,用于获取连接对象
    @Override
    public Connection getConnection() throws SQLException {
        if (pool.size()>0){
            Connection con = pool.remove(0);
            return con;
        }else{
            throw new RuntimeException("连接数量已用尽");
        }
    }

    // 定义getSize方法,获取连接池容器的大小
    public int getSize(){
        return pool.size();
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

public class DataSourceTest {
    public static void main(String[] args) throws SQLException {
        // 创建连接池对象
        MyDataSource dataSource = new MyDataSource();

        // 通过连接池对象获取连接对象
        Connection connection = dataSource.getConnection();

        // 查询学学生表的信息
        String sql = "SELECT * FROM user";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();

        while (resultSet.next()){
            System.out.print(resultSet.getInt("id"));
            System.out.println(resultSet.getString("username"));
        }

        JDBCUtils.close(connection,preparedStatement);
    }
}
归还连接
继承方式(不能用,理解思想即可)
  • 通过打印连接对象,发现DriverManager获取的连接实现类是JDBC4Connection

  • 那我们就可以自定义一个类,继承JDBC4Connection这个类,重写close(方法,完成连接对象的归还

  • 实现步骤
    ①定义一个类,继承JDBC4Connection.
    ②定义Connection连接对象和连接池容器对象的成员变量。
    ③通过有参构造方法完成对成员变量的赋值。
    ④重写close方法,将连接对象添加到池中。

public class MyConnection1 extends JDBC4Connection {
    private Connection connection;
    private List<Connection> pool;

    public MyConnection1(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url, Connection connection, List<Connection> pool) throws SQLException {
        super(hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url);
        this.connection = connection;
        this.pool = pool;
    }

    @Override
    public void close() throws SQLException{
        pool.add(connection);
    }
}
装饰设计模式
  • 我们可以自定义-个类实现Connection接口。这样就具备了和JDBC4Connection相同的行为了
  • 重写close(方法,完成连接的归还。其余的功能还调用mysql驱动包实现类原有的方法即可
  • 实现步骤:
    ①定义一个类,实现Connection接口
    ②定义Connection连接对象和连接池容器对象的成员变量
    ③通过有参构造方法完成对成员变量的赋值
    ④重写close(方法,将连接对象添加到池中
    ⑤剩余方法,只需要调用mysql驱动包的连接对象完成即可
    ⑥在自定义连接池中,将获取的连接对象通过自定义连接对象进行包装

注:这里把开头的几个做了个模板,后面的没做

package com.BJ.JDBC.JDBCPool.Demo3;

import java.sql.*;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

public class MyConnection2 implements Connection {
    private Connection connection;
    private List<Connection> pool;

    public MyConnection2(Connection connection, List<Connection> pool) {
        this.connection = connection;
        this.pool = pool;
    }

    @Override
    public Statement createStatement() throws SQLException {
        return connection.createStatement();
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        return connection.prepareStatement(sql);
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        return connection.prepareCall(sql);
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
        return null;
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {

    }

    @Override
    public boolean getAutoCommit() throws SQLException {
        return false;
    }

    @Override
    public void commit() throws SQLException {

    }

    @Override
    public void rollback() throws SQLException {

    }

    @Override
    public void close() throws SQLException {
        pool.add(connection);
    }

    @Override
    public boolean isClosed() throws SQLException {
        return false;
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        return null;
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {

    }

    @Override
    public boolean isReadOnly() throws SQLException {
        return false;
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {

    }

    @Override
    public String getCatalog() throws SQLException {
        return null;
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {

    }

    @Override
    public int getTransactionIsolation() throws SQLException {
        return 0;
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
        return null;
    }

    @Override
    public void clearWarnings() throws SQLException {

    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return null;
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
        return null;
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {

    }

    @Override
    public void setHoldability(int holdability) throws SQLException {

    }

    @Override
    public int getHoldability() throws SQLException {
        return 0;
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
        return null;
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        return null;
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {

    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {

    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
        return null;
    }

    @Override
    public Clob createClob() throws SQLException {
        return null;
    }

    @Override
    public Blob createBlob() throws SQLException {
        return null;
    }

    @Override
    public NClob createNClob() throws SQLException {
        return null;
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
        return null;
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
        return false;
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {

    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {

    }

    @Override
    public String getClientInfo(String name) throws SQLException {
        return null;
    }

    @Override
    public Properties getClientInfo() throws SQLException {
        return null;
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
        return null;
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
        return null;
    }

    @Override
    public void setSchema(String schema) throws SQLException {

    }

    @Override
    public String getSchema() throws SQLException {
        return null;
    }

    @Override
    public void abort(Executor executor) throws SQLException {

    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {

    }

    @Override
    public int getNetworkTimeout() throws SQLException {
        return 0;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}
适配器设计模式
  • 我们可以提供一个适配器类,实现Connection接口,将所有方法进行实现(除了close方法)
  • 自定义连接类只需要继承这个适配器类,重写需要改进的close()方法即可
  • 实现步骤
    ①定义一个适配器类,实现Connection接口。
    ②定义Connection连接对象的成员变量。
    ③通过有参构造方法完成对成员变量的赋值。
    ④重写所有方法(除了close ) ,调用mysq驱动包的连接对象完成即可.
    ⑤定义一一个连接类,继承适配器类。
    ⑥定义Connection连接对象和连接池容器对象的成员变量,并通过有参构造进行赋值。
    ⑦重写close0方法,完成归还连接。
    ⑧在自定义连接池中,将获取的连接对象通过自定义连接对象进行包装。
动态代{过}{滤}理模式
  • 我们可以通过Proxy来完成对Connection实现类对象的代{过}{滤}理

  • 代{过}{滤}理过程中判断如果执行的是close方法,就将连接归还池中。如果是其他方法则调用连接对象原来的功能即可

  • 动态代{过}{滤}理:在不改变目标对象方法的情况下对方法进行增强

    • 组成:
      被代{过}{滤}理的对象:真实的对象
      代{过}{滤}理对象:内存中的一个对象
    • 要求:
      代{过}{滤}理对象必须和被代{过}{滤}理对象实现相同的接口
    • 实现
      Proxy.newProxyInstance()
  • 实现步骤
    ①定义一个类,实现DataSource接口
    ②定义一个容器,用于保存多个Connection连接对象
    ③定义静态代码块,通过JDBC工具类获取10个连接保存到容器中
    ④重写getConnection方法,从容器中获取一个连接
    ⑤通过Proxy代{过}{滤}理,如果是close方法,就将连接归还池中。如果是其他方法则调用原有功能
    ⑥定义getSize方法,用于获取容器的大小并返回

C3P0

步骤
①导入jar包。
②导入配置文件到src目录下。
③创建C3PO连接池对象。
④获取数据库连接进行使用。

注:C3P0的配置文件会自动加载,但是必须交c3p0-config.xml或c3p0-config.properties(配置文件可以去百度找,基本上都是一样的)
    public class C3P0Test1 {
    public static void main(String[] args) throws SQLException {
        // 创建c3p0的数据库连接池对象
        DataSource dataSource = new ComboPooledDataSource();
        // 通过连接池对象获取数据库连接
        Connection connection = dataSource.getConnection();
        // 执行操作
        String sql = "SELECT * FROM user";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery(sql);
//        - 处理结果
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");
            System.out.print(id + "  ");
            System.out.println(username);
        }
//        - 释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

<c3p0-config>
    <!--使用默认的配置读取连接池对象-->
    <default-config>
        <!--连接参数-->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost/qq</property>
        <property name="user">root</property>
        <property name="password">root</property>
        <!-- 连接池参数 -->
        <!-- 初始化的连接数量 -->
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <!-- 最大连接数量 -->
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
        <property name="maxStatements">200</property>
        <!-- 超时时间 -->
        <property name="checkoutTimeout">3000</property>
    </default-config>

</c3p0-config>

Druid

①导入jar包。
②编写配置文件,放在src目录下。
③通过Properties集合加载配置文件。
④通过Druid连接池工厂类获取数据库连接池对象。
⑤获取数据库连接进行使用。
注:Druid不会自动加载配置文件,需要我们手动加载,但是文件的名称可以自定义
/**
 * 1.通过Properties集合,加载配置文件
 * 2.通过Druid连接池工厂类获取数据库连接池对象
 * 3.通过连接池对象获取数据库连接
 */
public class DruidTest1 {
    public static void main(String[] args) throws Exception {
        // 获取配置文件
        InputStream is = DruidTest1.class.getClassLoader().getResourceAsStream("druid.properties");
        // 1.通过Properties集合,加载配置文件
        Properties properties = new Properties();
        properties.load(is);

        // 通过Druid连接池工厂类获取数据库连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        // 3.通过连接池对象获取数据库连接
        Connection connection = dataSource.getConnection();

        // 执行操作
        String sql = "SELECT * FROM user";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery(sql);
//        - 处理结果
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");

            System.out.print(id + "  ");
            System.out.println(username);
        }
//        - 释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

配置文件:(文件名:druid.properties)
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/qq
username=root
password=root
# 初始化连接数量
initialSize=5
# 最大连接数量
maxActive=10
# 超时时间
maxWait=3000

数据库连接池工具类抽取

/**
 * 数据库连接池的工具类
 */
public class DataSourceUtils {
    // 1.私有化构造方法
    private DataSourceUtils(){}
    // 2.声明数据源变量
    private static DataSource dataSource;
    // 3.提供静态代码块,完成配置文件的加载和获取数据库连接池对象
    static {
        try{
            // 获取配置文件
            InputStream is = DataSourceUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            // 通过Properties集合,加载配置文件
            Properties properties = new Properties();
            properties.load(is);

            // 通过Druid连接池工厂类获取数据库连接池对象
            dataSource= DruidDataSourceFactory.createDataSource(properties);

        }catch (Exception e){
            e.printStackTrace();
        }
    }
    // 4.提供一个获取数据库连接的方法

    public static Connection getConnection(){
        Connection con = null;

        try {
            con = dataSource.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return con;
    }

    // 5.提供一个获取数据连接池对象的方法
    public static  DataSource getDataSource(){
        return  dataSource;
    }

    // 6.释放资源
    public static void close(Connection con, Statement stat, ResultSet rs){
        if (con!=null){
            try {
                con.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (stat!=null){
            try {
                stat.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    public static void close(Connection con, Statement stat){
        if (con!=null){
            try {
                con.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (stat!=null){
            try {
                stat.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

免费评分

参与人数 5吾爱币 +5 热心值 +5 收起 理由
柑桔 + 1 + 1 用心讨论,共获提升!
zxzzxz461 + 1 + 1 谢谢@Thanks!
blank_verse + 1 + 1 用心讨论,共获提升!
vethenc + 1 + 1 谢谢@Thanks!
努力加载中 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

老子就是拽 发表于 2021-7-24 11:56
666666
layuai 发表于 2021-7-24 12:35
可以,内容要点基本提到,具体内容还要个人自学一下
风夜 发表于 2021-7-24 12:50
头像被屏蔽
16du 发表于 2021-7-24 13:21
提示: 作者被禁止或删除 内容自动屏蔽
huhu1982 发表于 2021-7-24 13:23
谢谢分享
 楼主| LongJL 发表于 2021-7-24 13:28
16du 发表于 2021-7-24 13:21
大佬写的好,排版怎么这么工整的呢?

排版用markdown啊
137RickSanchez 发表于 2021-7-24 13:30
感谢分享,刚好需要。
xilongy 发表于 2021-7-24 13:50
感谢分享,学习中。
Ajin1989 发表于 2021-7-24 13:51
谢谢了 我要多看看
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 20:16

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表