jdbc-2-基本数据库操作

Posted 懒佯佯大哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdbc-2-基本数据库操作相关的知识,希望对你有一定的参考价值。

简介:

  • 数据库连接:用于向数据库发送请求,一个数据库连接就是一个socket连接
  • CRUD:crud是指在做计算处理时的增加(Create)、读取(Retrieve)、更新(Update)和删除(Delete)几个单词的首字母简写。crud主要被用在描述软件系统中数据库或者持久层的基本操作功能。

java

  • 三种操作方式

    • Statement:用于执行不带参数的简单sql语句—现在很少用:
      • sql注入:因为它的语句,只是用string作了简单的拼接
      • 性能差等等问题
    • PreparedStatement:用于执行预编译sql语句
    • CallableStatement:用于执行对存储过程的调用
  • 类图关系:

    mysql实现了jdbc的三个Statment操作接口

  • 重点关注PrepareStatement

代码

  • 前置:封装一个获取连接的工具类:
package utils;

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

public class ConnGetUtil 
    /**
     * 加载配置文件获取一个连接
     */
    public static Connection getConnection() throws Exception 
        InputStream resourceAsStream = ConnGetUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);

        Class.forName(properties.getProperty("driverClass"));
        Connection connection = DriverManager.getConnection(properties.getProperty("url"),
                properties.getProperty("user"),
                properties.getProperty("password"));
        return connection;
    

    /**
     * 关闭数据库连接和PreparedStatment
     */
    public static void closeConnection(Connection connection, PreparedStatement ps, ResultSet resultSet) 
        if (ps != null) 
            try 
                ps.close();
             catch (SQLException throwables) 
                throwables.printStackTrace();
            
        
        if (connection != null) 
            try 
                connection.close();
             catch (SQLException throwables) 
                throwables.printStackTrace();
            
        
        if (resultSet != null) 
            try 
                resultSet.close();
             catch (SQLException throwables) 
                throwables.printStackTrace();
            
        
    


Statement代码示例:
  • 由于Statement存在不安全的场景:故这里只做简单介绍:
package StatementTest;

import org.junit.Test;
import utils.ConnGetUtil;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

public class Test1 
    @Test
    public void test01() throws Exception 
        Connection connection = ConnGetUtil.getConnection();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from user_table;");
        statement.execute("insert into user_table(user , password, balance) values ('qianliu', '333', 200)");
//        System.out.println(resultSet.toString());
//        System.out.println(resultSet.getArray(1));
    


  • 输出略
PrepareStatement代码示例:
  • 通用操作:
package PreparedStatementTest;

import domain.Order;
import domain.UserTable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import utils.ConnGetUtil;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

/**
 * 将Test1中的CRUD操作,封装为通用的,不再限制死
 */
public class Test2Common 

    private Connection connection;
    private PreparedStatement preparedStatement;
    private ResultSet resultSet;

    @Before
    public void setConnection() 
        try 
            connection = ConnGetUtil.getConnection();
         catch (Exception e) 
            System.out.println("获取连接失败");
            e.printStackTrace();
        
    

    @After
    public void close() 
        ConnGetUtil.closeConnection(connection, preparedStatement, resultSet);
    

    /**
     * 1. 开始封装通用的查询操作
     */
    public List<Object> queryUserTable(String sql, Object... args) throws Exception
        // 1.先获取连接
        connection = ConnGetUtil.getConnection();
        // 2.获取PreparedStatement,并进行预编译
        preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i < args.length; i++) 
            preparedStatement.setObject(i+1, args[i]);
        
        // 3.执行查询
        ResultSet resultSet = preparedStatement.executeQuery();
        // 4.通过反射赋值
        List<Object> result = new ArrayList<>();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        while (resultSet.next()) 
            UserTable userTable = new UserTable();
            for (int i = 0; i < columnCount; i++) 
                String columnName = metaData.getColumnName(i + 1);
                Object object = resultSet.getObject(i + 1);
                // 反射获取UserTable中的字段
                Field declaredField = UserTable.class.getDeclaredField(columnName);
                if (declaredField != null) 
                    declaredField.setAccessible(true);
                    declaredField.set(userTable, object);
                
            
            System.out.println(userTable);
            result.add(userTable);
        
        return result;
    

    @Test
    public void testQuery() throws Exception 
        System.out.println("============== 查询一条 ==============");
        String sql = "select id, user, password, balance from user_table where id = ?;";
        queryUserTable(sql, 1);

        System.out.println("============== 查询所有 ==============");
        sql = "select id, user, password, balance from user_table;";
        queryUserTable(sql);

        System.out.println("============== 只查一个字段 ==============");
        sql = "select user from user_table;";
        queryUserTable(sql);
    


    /**
     * 2. 使用泛型操作
     */
    public <T> List<T> queryWithGeneric(String sql, Class<T> tClass, Object... args) throws Exception
        // 1.先获取连接
        connection = ConnGetUtil.getConnection();
        // 2.获取PreparedStatement,并进行预编译
        preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i < args.length; i++) 
            preparedStatement.setObject(i+1, args[i]);
        
        // 3.执行查询
        ResultSet resultSet = preparedStatement.executeQuery();
        // 4.通过反射赋值
        List<T> result = new ArrayList<>();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        while (resultSet.next()) 
            T t = tClass.newInstance();
            for (int i = 0; i < columnCount; i++) 
                // 这里需要使用getColumnLable获取label标志(别名),不能用getColumnName(只能获取表的字段名)
//                String columnName = metaData.getColumnName(i + 1);
                String columnLabel = metaData.getColumnLabel(i + 1);
                Object object = resultSet.getObject(i + 1);
                // 反射获取UserTable中的字段
                Field declaredField = tClass.getDeclaredField(columnLabel);
                if (declaredField != null) 
                    declaredField.setAccessible(true);
                    declaredField.set(t, object);
                
            
            System.out.println(t);
            result.add(t);
        
        return result;
    

    /**
     * 用泛型测试最通用的
     * @throws Exception
     */
    @Test
    public void testQueryGeneric() throws Exception 
        System.out.println("============== 使用泛型, 查询一条 ==============");
        String sql = "select id, user, password, balance from user_table where id = ?;";
        queryWithGeneric(sql, UserTable.class, 1);

        System.out.println("============== 使用泛型, 查询所有 ==============");
        sql = "select id, user, password, balance from user_table;";
        queryWithGeneric(sql, UserTable.class);
    

    /**
     * 测试数据库字段和类字段不匹配的情况:
     *  1. select的时候,需要对字段设置别名
     *  2. 通用里面,需要用getColumnLabel()获取别名,不能使用getColumnName
     */
    @Test
    public void testOrder() throws Exception 
        System.out.println("============== 使用泛型, 查询所有 ==============");
        String sql = "select order_id orderId, order_name orderName, order_date orderDate from `order`;";
        queryWithGeneric(sql, Order.class);
    


输出:

Wed Jun 10 22:19:53 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
============== 使用泛型, 查询一条 ==============
Wed Jun 10 22:19:53 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
UserTableid=1, user='lisi', password='456', balance=9999
============== 使用泛型, 查询所有 ==============
Wed Jun 10 22:19:53 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
UserTableid=1, user='lisi', password='456', balance=9999
UserTableid=2, user='qianliu', password='333', balance=200
UserTableid=3, user='wangwu', password='123_new', balance=1000
UserTableid=4, user='zhagnsan', password='123', balance=1000
UserTableid=12, user='lisi', password='777', balance=9999
UserTableid=13, user='lisi', password='777', balance=1500
UserTableid=22, user='qianliu', password='333', balance=200
Wed Jun 10 22:19:53 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
============== 使用泛型, 查询所有 ==============
Wed Jun 10 22:19:53 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
OrderorderId=1, orderName='pens', orderDate=2000-01-01 00:00:00.0
OrderorderId=2, orderName='food', orderDate=1995-03-12 00:00:00.0
Wed Jun 10 22:19:53 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
============== 查询一条 ==============
Wed Jun 10 22:19:53 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
UserTableid=1, user='lisi', password='456', balance=9999
============== 查询所有 ==============
Wed Jun 10 22:19:53 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
UserTableid=1, user='lisi', password='456', balance=9999
UserTableid=2, user='qianliu', password='333', balance=200
UserTableid=3, user='wangwu', password='123_new', balance=1000
UserTableid=4, user='zhagnsan', password='123', balance=1000
UserTableid=12, user='lisi', password='777', balance=9999
UserTableid=20, user='lisi', password='777', balance=1500
UserTableid=22, user='qianliu', password='333', balance=200
============== 只查一个字段 ==============
Wed Jun 10 22:19:53 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
UserTableid=0, user='lisi', password='null', balance=0
UserTableid=0, user='qianliu', password='null', balance=0
UserTableid=0, user='wangwu', password='null', balance=0
UserTableid=0, user='zhagnsan', password='null', balance=0
UserTableid=0, user='lisi', password='null', balance=0
UserTableid=0, user='qianliu', password='null', balance=0
  • 批量操作效率:
package PreparedStatementTest;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import sun.lwawt.macosx.CSystemTray;
import utils.ConnGetUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * 测试批量提交
 */
public class TestBatch 


    private Connection connection;
    private PreparedStatement preparedStatement;
    private ResultSet resultSet;

    @Before
    public void setConnection() 
        try 
            connection = ConnGetUtil.getConnection();
         catch (Exception e) 
            System.out.println("获取连接失败");
            e.printStackTrace();
        
    

    @After
    public void close() 
        ConnGetUtil.closeConnection(connection, preparedStatement, resultSet);
    

    /**
     * 测试批量提交
     *  方式1:使用Statement
     *  方式2:使用PreparedStatement直接提交,简化sql翻译
     *          因为PreparedStatement只翻译一次,故下面四项,都只做一次
     *              语法检查:
     *              语义检查:
     *              翻译成二进制指令:
     *              缓存
     *          后续占位符传入的时候,只需要传参过去即可
     *  方式3:使用PreparedStatement批量提交
     *  方式4:使用PreparedStatement批量提交+一次性提交(利用AutoCommit方式)
     */
    @Test
    public void testBatch() throws Exception
        int batchSize = 20000;

        System.out.println("================ 方式1:使用Statement ================");
        long start = System.currentTimeMillis();
        Statement statement = connection.createStatement();
        for (int i = 0; i < batchSize; i++) 
            String sql = "insert into batch_test(name) values('statement" + i + "');";
            statement.execute(sql);
        
        statement.close();
        System.out.println("时间花费为:" + (System.currentTimeMillis() - start) + " ms");

        System.out.println("================ 方式2:使用PreparedStatement直接提交,简化sql翻译 ================");
        start = System.currentTimeMillis();
        preparedStatement = connection.prepareStatement("insert into batch_test(name) values(?);");

        for (int i = 0; i < batchSize; i++) 
            preparedStatement.setString(1, "preparedStatement" + i);
            preparedStatement.execute();
        
        preparedStatement.close();
        System.out.println("时间花费为:" + (System.currentTimeMillis() - start) + " ms");

        System.out.println("================ 方式3:使用PreparedStatement批量提交 ================");
        start = System.currentTimeMillis();
        preparedStatement = connection.prepareStatement("insert into batch_test(name) values(?);");

        for (int i = 0; i < batchSize; i++) 
            preparedStatement.setString(1, "preparedStatement" + i);
            preparedStatement.addBatch();
            if (i % 500 == 0

以上是关于jdbc-2-基本数据库操作的主要内容,如果未能解决你的问题,请参考以下文章

操作系统基本原理

MySQL基本操作

vue 基本操作

vue 基本操作

MySQL数据库基本操作

MySQL基本操作