Mysql JDBC和事务(细致而易懂)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


安装环境

1.jdk17

2.MySQL8


一;JDBC

1.jdbc概述

JDBC指Java数据库连接,是一种标准Java应用编程接口(JAVA API),用来连接Java编程语言和广泛的数据库。 其实就是说,jdbc就是Java用来操作数据库的一个API。

2.常见的JDBC组件

JDBC的API提供了以下接口和类:

         Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商要来实现此接口。

Connection conn = driver.connect(url,properties);

               connect(url, properties):  连接数据库的方法。

                url: 连接数据库的URL

                password: 数据库用户密码

        DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序

 Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");
        Driver dr = (Driver) aClass.newInstance();
        String url = "jdbc:mysql://localhost:3306/h3?serverTimezone=UTC&useSSL=false";
        String user = "root";
        String password = "123456";
        DriverManager.registerDriver(dr);
        Connection connection = DriverManager.getConnection(url,user,password);

                registerDriver(driver)  : 注册驱动类对象

                Connection getConnection(url,user,password):  获取连接对象

        Connection接口: 表示java程序和数据库的连接对象。

                Statement createStatement() : 创建Statement对象

                PreparedStatement prepareStatement(String sql):创建PreparedStatement对象

                CallableStatement prepareCall(String sql):创建CallableStatement对象

         Statement接口: 用于执行静态的sql语句,就是说不可以注入参数

                int executeUpdate(String sql)  : 执行静态的更新sql语句(DDL,DML)

                ResultSet executeQuery(String sql)  :执行的静态的查询sql语句(DQL)

         PreparedStatement接口:用于执行预编译sql语句,可以注入参数

//将sql语句放入批处理包
preparedStatement.addBatch();
//执行包里的sql语句         
preparedStatement.executeBatch();
//清空一下
preparedStatement.clearBatch();

                int executeUpdate() : 执行预编译的更新sql语句(DDL,DML)

                ResultSet executeQuery()  : 执行预编译的查询sql语句(DQL)

        ResultSet接口:用于封装查询出来的数据

//和数据库中的类型一一匹配
resultSet.getObject(); // 不知道列类型的情况下使用
// 如果知道列的类型就使用指定的类型
resultSet.getString(); 
resultSet.getDate();
resultSet.getInt();
resultSet.getDouble();
resultSet.next()  // 移动到下一个


             
3.实例

MySQL配置文件.properties

user=root
password=123456
//serverTimezone=UTC 修改时区
//rewriteBatchedStatements=true 添加批量操作的功能
//useSSL=false 是说是否使用SSL连接,我们这里选false
url=jdbc:mysql://localhost:3306/h3?serverTimezone=UTC&useSSL=false&rewriteBatchedStatements=true
//不同的版本的driver可能不一样,比如说低版本的可能是com.mysql.jdbc.Driver
//你要是不确定你的版本,可以两种都试一下
driver=com.mysql.cj.jdbc.Driver

JDBCutils方法类

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

//工具类完成mysql的连接与释放
public class JDBCUtils {
    private static String user;
    private static String password;
    private static String url;
    private static String driver;
    static {
        Properties properties =new Properties();
        try {
            //这里使用properties配置文件对user,url等进行赋值
            properties.load(new FileInputStream("src\\mysql.properties"));
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            url = properties.getProperty("url");
            //driver = com.mysql.cj.jdbc.Driver
            //但是不同的MySQL版本有不同的写法我这个版本是这么写
            //但是低的版本可能是com.mysql.jdbc.Driver
            driver = properties.getProperty("driver");
            //第一步:加载驱动
            //固定写法
            Class.forName(driver);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection(){
        try {
            //第二步获取连接
            return DriverManager.getConnection(url,user,password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public static void close(ResultSet set, Statement statement,Connection connection){
        try{
            if(set != null){
                //关闭结果集的连接
                set.close();
            }
            if(statement !=null){
                //关闭statement连接
                statement.close();
            }
            if(connection !=null){
                //关闭连接
                connection.close();
            }
        }catch (SQLException e){
            throw new RuntimeException(e);
        }

    }
}

JDBCtest测试类

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

public class JDBCUtils_use {
    public static void main(String args[]){
        JDBCUtils_use h = new JDBCUtils_use();
        h.test();
    }
    public void test(){
        Connection connection = null;
        String sql = "update actor set name = ? where id = ?";
        PreparedStatement preparedStatement = null;
        try{
            //获取链接
            connection = JDBCUtils.getConnection();
            //预加载sql语句
            preparedStatement = connection.prepareStatement(sql);
            //向sql语句注入值
            preparedStatement.setString(1,"周星驰");
            //向sql语句注入值
            preparedStatement.setInt(2,3);
            //执行dml操作
            preparedStatement.executeUpdate();
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            //关闭连接
            JDBCUtils.close(null, preparedStatement,connection );
        }
    }
}

 二.preparedstament和statement的区别

Statement:直接操作sql,不进行预编译,不带参数;

PreparedStatement:进行预编译,可带参数,还可以批量处理;

下面这张图就可以很好的解释statement不可以带参数的问题,statement要执行的sql语句必须是完整的。

 还有一个好处就是preparedstatement可以预防SQL注入的问题

假如登录SQL为select * from user where name='zs' and password='123' ,如果在登录框密码处输入 “123 or 1=1”,那么SQL就成为了select * from user where name='zs and password='123' or 1=1 ,这个时候因为or 后面是1=1,所以不管别人输入什么命令他都会登入成功,比如说你再输入“123456 or 1=1”,他也能够登入成功。但是但我们使用preparedstatement的时候,无论我们往占位符里输入什么,他都会被认为是sql语句之外的东西,比如说继续向上面一样输入 “123 or 1=1”,他就会被识别为passward=”123 or 1=1“,而不是 password='123' or 1=1。

三.批量处理 

可以使用preparedstatement对sql语句进行批处理

注意:批处理的时候,你的url后面一定要加rewriteBatchedStatements=true 去添加批量操作的功能,不然是无法执行的。

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

public class pilian {
    public static void main(String args[]) throws Exception {
        pilian h = new pilian();
        h.batch();
    }
    public void batch() throws Exception{
        Connection connection = JDBCUtils.getConnection();
        String sql = "insert into sallary values (?,?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        long start =System.currentTimeMillis();
        for(int i = 0;i < 5000;i++){
            preparedStatement.setInt(1,i);
            preparedStatement.setString(2,"梅艳芳"+i);
            preparedStatement.setInt(3,1000);
            //将sql语句放入批处理包
            preparedStatement.addBatch();
            if((i +1) % 1000 ==0){//每满一千条执行一次
                preparedStatement.executeBatch();
                //清空一下
                preparedStatement.clearBatch();
            }


        }
        long end = System.currentTimeMillis();
        System.out.println("批量耗时"+(end - start));
        JDBCUtils.close(null,preparedStatement,connection);
    }
}

 四.事务提交控制

如果我们不设置connection.setAutoCommit(false)的话,我们每执行一次sql语句就会提交一次,当我们设置之后,我们可以选择提交的时候,比如说这里,只有当sql1和sql2都成功执行的时候才可以提交 connection.commit()(就是要我们手动提交)。

package SQL1.SQL11;

import SQL1.utils.JDBCUtils;

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

public class transaction {//事务解决
    public static void main(String args[]){
        transaction h = new transaction();
        h.notr();
    }
    public void notr(){
        Connection connection = null;
        String sql1 = "update sallary set wealth = wealth -100 where id = 1";
        String sql2 = "update sallary set wealth = wealth +100 where id = 2";
        PreparedStatement preparedStatement = null;
        try{
            connection = JDBCUtils.getConnection();
            connection.setAutoCommit(false);//不会自动提交
            preparedStatement = connection.prepareStatement(sql1);
            preparedStatement.executeUpdate();
           // int i = 1/0;
            preparedStatement = connection.prepareStatement(sql2);
            preparedStatement.executeUpdate();
            connection.commit();//手动提交
        }catch (SQLException e){

            try {
                //默认回滚到开始状态
                connection.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            JDBCUtils.close(null, preparedStatement,connection );
        }
    }
}

最后 

 本次的实验就到这里了,如果有讲得不对的或者有所欠缺得地方,欢迎大家来指正与补充,创作不易,还请点个赞再走吧!后面我还会更新其他计算机方面的博客,咱们下篇博客再见!

猜你喜欢

转载自blog.csdn.net/weixin_64972949/article/details/130135896