• JDBC


    1. 概述

    以maven3.6.3+mysql5.7+8.0的驱动包演示(8.0兼容5.7 5.6)

    五大步骤

    2. 加载并注册驱动

    String driver = "com.mysql.cj.jdbc.Driver";
    
    Class.forName(driver);
    

    加载这个类就可以执行静态代码块进行注册:

    3. 获取数据库连接

    String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
    String username = "root";
    String password = "root";
    
    Connection connection = DriverManager.getConnection(url, username, password);
    

    4. 操作或访问数据库

    Statement

    通过调用 Connection 对象的 createStatement() 方法创建该对象。该对象用于执行静态的 SQL 语句,并且返回执行结果

    Statement statement = connection.createStatement();
    

    Statement 接口中定义了下列方法用于执行 SQL 语句:

    • int excuteUpdate(String sql):执行更新操作INSERTUPDATEDELETE
    • ResultSet excuteQuery(String sql):执行查询操作SELECT

    ResultSet

    ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集

    ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前

    常用方法:

    • boolean next():移动到下一行
    • xxx getXxx(String columnLabel):columnLabel 使用 SQL AS 子句指定的列标签。如果未指定 SQL AS 子句,则标签是列名称
    • xxx getXxx(int index) :索引从 1 开始,针对结果集不针对表

    查询示例代码:

    public static void main(String[] args) throws Exception {
        String url = "jdbc:mysql://localhost:3306/girls?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
        String username = "root";
        String password = "root";
        String driver = "com.mysql.cj.jdbc.Driver";
    
        // 1.加载驱动并注册
        Class.forName(driver);
        // 2.获取连接对象
        Connection connection = DriverManager.getConnection(url, username, password);
    
        // 3.1 编写sql
        String sql = "select * from `student`";
        // 3.2 获取Statement对象
        Statement statement = connection.createStatement();
    
        // 4.执行sql
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()) {
            System.out.print(resultSet.getInt("id"));
            System.out.print("	");
            System.out.print(resultSet.getString("name"));
            System.out.print("	");
            System.out.print(resultSet.getInt("age"));
            System.out.print("
    ");
        }
    
        // 5.释放资源
        resultSet.close();
        statement.close();
        connection.close();
    }
    

    PrepatedStatement

    可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象。PreparedStatement接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句

    方法和Statement一样,只不过没有参数

    PrepatedStatement可以解决的问题

    • SQL拼接
    • SQL注入
    • 处理Blob类型数据

    插入示例代码:

    public static void main(String[] args) throws Exception {
        String url = "jdbc:mysql://localhost:3306/girls?useSSL=false&serverTimezone=Asia/Shanghai";
        String username = "root";
        String password = "root";
        String driver = "com.mysql.cj.jdbc.Driver";
    
        // 1.加载驱动并注册
        Class.forName(driver);
        // 2.获取连接对象
        Connection connection = DriverManager.getConnection(url, username, password);
    
        // 3.1 编写预sql
        String sql = "insert into student(`name`,`age`) values(?,?)";
        // 3.2 获取PreparedStatement对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        // 3.3 对?进行填充
        preparedStatement.setString(1, "王五"); // 从1开始
        preparedStatement.setInt(2, 17);
    
        // 4.执行sql
        int i = preparedStatement.executeUpdate();
        System.out.println(i > 0 ? "执行成功" : "执行失败");
    
        // 5.释放资源
        preparedStatement.close();
        connection.close();
    }
    

    CallableStatement

    5. 释放资源

    ConnectionStatementResultSet都是应用程序和数据库服务器的连接资源,使用后一定要关闭,可以在finally中关闭,按先获取后关闭的原则

    事务

    需要确保是同一个Connection才有效

    Connection connection = JDBCUtil.getConnection();
    connection.setAutoCommit(false); // 开启事务
    connection.rollback();
    connection.commit();
    connection.setAutoCommit(true); // 关闭事务
    

    批处理

    如果要使用批处理功能,请再url中加参数rewriteBatchedStatements=true

    常用方法:

    • addBatch():添加需要批量处理的SQL语句或参数
    • executeBatch():执行批量处理语句;
    • clearBatch():清空批处理包的语句
    @Test
    public void testJDBC3() throws Exception {
        Connection connection = JDBCUtil.getConnection();
        PreparedStatement statement = connection.prepareStatement("insert into `student`(`name`, `age`) values(?,?)");
        for (int i = 0; i < 50000; i++) {
            statement.setString(1, "张三" + i);
            statement.setInt(2, i);
            statement.addBatch();
            if (i%1000==0) {
                statement.executeBatch();
                statement.clearBatch();
            }
        }
        statement.executeBatch();
    
        JDBCUtil.close(connection, null, statement);
    }
    

    Blob格式

    插入

    @Test
    public void testJDBC4() throws Exception {
        Connection connection = JDBCUtil.getConnection();
        PreparedStatement statement = connection.prepareStatement("insert into `student`(`name`, `age`, `photo`) values(?,?,?)");
        statement.setString(1, "张三");
        statement.setInt(2, 14);//
        // String filePath = JDBCTest.class.getResource("/").getPath() + "动漫头像.jpg";
        // statement.setBlob(3, new FileInputStream(filePath));
        statement.setBlob(3, getClass().getResourceAsStream("/动漫头像.jpg")); // 放在resources目录下
        int i = statement.executeUpdate();
        System.out.println(i > 0 ? "success" : "fail");
    
        JDBCUtil.close(connection, null, statement);
    }
    

    读取

    @Test
    public void testJDBC5() throws Exception {
        Connection connection = JDBCUtil.getConnection();
        PreparedStatement statement = connection.prepareStatement("select * from `student` where `id` = ?");
        statement.setInt(1, 2);
        ResultSet resultSet = statement.executeQuery();
        resultSet.next();
        InputStream is = resultSet.getBinaryStream("photo");
    
        FileOutputStream fos = new FileOutputStream("/Users/collin/IdeaProjects/Kuang/JavaWeb02-muti-maven/JDBC/src/test/resources/动漫头像1.jpg");
        int len = 0;
        byte[] b = new byte[1024];
        while ((len = is.read(b)) != -1) {
            fos.write(b, 0, len);
        }
    
        JDBCUtil.close(connection, resultSet, statement);
        is.close();
        fos.close();
    }
    

    封装JDBC

    需要建立jdbc.properties文件和引入BeanUtils

    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.sql.*;
    import java.util.*;
    
    public class JDBCUtil {
        private static String DRIVER;
        private static String URL;
        private static String USERNAME;
        private static String PASSWORD;
    
        private static Connection connection;
    
        static {
            try {
                Properties properties = new Properties();
                properties.load(JDBCUtil.class.getResourceAsStream("/jdbc.properties"));
                DRIVER = properties.getProperty("driver");
                URL = properties.getProperty("url");
                USERNAME = properties.getProperty("username");
                PASSWORD = properties.getProperty("password");
    
                // 注册驱动
                Class.forName(DRIVER);
            } catch (ClassNotFoundException | IOException e) {
                e.printStackTrace();
            }
        }
    
        public static Connection getConnection() throws SQLException {
            if (connection == null) {
                return DriverManager.getConnection(URL, USERNAME, PASSWORD);
            }
            return connection;
        }
    
        public static void beginTransaction() throws SQLException {
            getConnection().setAutoCommit(false);
        }
    
        public static void commitTransaction() throws SQLException {
            getConnection().commit();
            getConnection().setAutoCommit(true);
        }
    
        public static void rollBackTransaction() throws SQLException {
            getConnection().rollback();
            getConnection().setAutoCommit(true);
        }
    
        public static void close(Connection connection, ResultSet resultSet, Statement statement) throws SQLException {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    
        public static void close(ResultSet resultSet, Statement statement) throws SQLException {
            close(null, resultSet, statement);
        }
    
    
        public static void close(Statement statement) throws SQLException {
            close(null, null, statement);
        }
    
        public static void closeConnection(Connection connection) throws SQLException {
            close(connection, null, null);
        }
    
        public static int update(String sqlStr, Object... params) throws SQLException {
            PreparedStatement preparedStatement = null;
            try {
                preparedStatement = getConnection().prepareStatement(sqlStr);
                for (int i = 0; i < params.length; i++) {
                    preparedStatement.setObject(i + 1, params[i]);
                }
                return preparedStatement.executeUpdate();
            } catch (SQLException e) {
                throw e;
            } finally {
                close(preparedStatement);
            }
        }
    
        public static List<Map<String, Object>> queryForMap(String querySql, Object... params) throws SQLException {
            List<Map<String, Object>> result = new ArrayList<>();
            PreparedStatement preparedStatement = null;
            ResultSet rs = null;
            try {
                preparedStatement = getConnection().prepareStatement(querySql);
                for (int i = 0; i < params.length; i++) {
                    preparedStatement.setObject(i + 1, params[i]); //Statement的参数下标从1
                }
                rs = preparedStatement.executeQuery();
                ResultSetMetaData resultMeta = rs.getMetaData(); // 获取结果集元信息
                while (rs.next()) {
                    Map<String, Object> record = new HashMap<>();
                    // 把结果集的一条记录封装到Map中,key-字段名, value-字段值
                    for (int i = 1; i <= resultMeta.getColumnCount(); i++) {
                        record.put(resultMeta.getColumnName(i), rs.getObject(i));
                    }
                    result.add(record);
                }
                return result;
            } catch (SQLException e) {
                throw e;
            } finally {
                close(rs, preparedStatement);
            }
        }
    
        public static <T> List<T> queryForBean(String querySql, Class<T> beanClass, Object... params) throws SQLException, InstantiationException, InvocationTargetException, IllegalAccessException {
            List<T> result = new ArrayList<>();
            PreparedStatement preparedStatement = null;
            ResultSet rs = null;
            try {
                preparedStatement = getConnection().prepareStatement(querySql);
                for (int i = 0; i < params.length; i++) {
                    preparedStatement.setObject(i + 1, params[i]); //Statement的参数下标从1
                }
                rs = preparedStatement.executeQuery();
                ResultSetMetaData resultMeta = rs.getMetaData();
                while (rs.next()) { // 循环封装数据
                    Map<String, Object> map = new HashMap<>();
                    for (int i = 1; i <= resultMeta.getColumnCount(); i++) {
                        map.put(resultMeta.getColumnName(i).toLowerCase(), rs.getObject(i));
                    }
                    T obj = beanClass.newInstance();
                    BeanUtils.populate(obj, map); // 反射创建实体对象,需要引入BeanUtils包
                    result.add(obj);
                }
                return result;
            } catch (SQLException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
                throw e;
            } finally {
                close(rs, preparedStatement);
            }
        }
    }
    

    Druid数据源

    当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close();但conn.close()并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。

    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.4</version>
    </dependency>
    

    Properties:

    url=jdbc:mysql://47.106.64.90:3306/girls?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username=root
    password=root
    driverClassName=com.mysql.cj.jdbc.Driver
    initialSize=10
    maxActive=20
    maxWait=1000
    filters=wall
    
    @Test
    public void testJDBC6() throws Exception {
        Properties pro = new Properties();
        pro.load(getClass().getClassLoader().getResourceAsStream("druid.properties"));
        DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);
        Connection connection = dataSource.getConnection();
        System.out.println(connection); // com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5e57643e
    }
    

    DBUtils

    Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装

    <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
    <dependency>
        <groupId>commons-dbutils</groupId>
        <artifactId>commons-dbutils</artifactId>
        <version>1.7</version>
    </dependency>
    

    QueryRunner

    该类封装了SQL的执行,是线程安全的

    更新

    插入

    批处理

    查询

    @Test
    public void testJDBC7() throws Exception {
        Properties pro = new Properties();
        pro.load(getClass().getClassLoader().getResourceAsStream("druid.properties"));
        DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);
    
        QueryRunner queryRunner = new QueryRunner(dataSource);
        String sql = "select * from student";
        List<Student> studentList = queryRunner.query(sql, new BeanListHandler<>(Student.class));
        for (Student student : studentList) {
            System.out.println(student);
        }
    }
    

    ResultSetHandler

    该接口有如下常用实现类可以使用:

    • BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中
    • BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里
    • ColumnListHandler:将结果集中某一列的数据存放到List中
    • MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值
    • MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
    • ScalarHandler:查询单个值
  • 相关阅读:
    Python安装
    php中奖概率算法,可用于刮刮卡,大转盘等抽奖算法
    关闭sublime自动检测更新提示
    Linux系统基本命令操作汇总
    jQuery各版本CDN
    【分享】每个 Web 开发者在 2021 年必须拥有 15 个 VSCode 扩展
    React & Redux 实战 Reminder Pro 项目 免费视频教程(5 个视频)
    Redux 入门教程(React 进阶)(20 个视频)
    Nodejs + Express + MongoDB 基础篇(17 个视频)
    轻松学 nodejs
  • 原文地址:https://www.cnblogs.com/shenleg/p/14267204.html
Copyright © 2020-2023  润新知