• 三十七、Java基础之JDBC


    一、Java代码使用JDBC之Statement

    1.六个步骤:

    /**
     * JDBC驱动六大步骤:
     * 1、注册数据库驱动,目的是为了让jvm可以识别mysql数据库驱动类
     * 2、获取和数据库的连接对象
     * 3、通过连接获取语句对象
     * 4、通过语句对象执行具体的DQL语句对象,返回结果集对象
     * 5、遍历结果集,取出每条记录
     * 6、关闭数据库相 关资源
     */

    2.用到的方法:

    //1、注册数据库驱动:
    Driver driver = new com.mysql.jdbc.Driver();
     //通过驱动管理器注册驱动
    DriverManager.registerDriver(driver);
    //2、获取和数据库的连接
    //a、准备数据库相关资源
    String username="root";
    String password = "123456";
    String url="jdbc:mysql://localhost:3306/test-csj";
    //b、获取和数据库的连接
    conn = DriverManager.getConnection(url, username, password);
    //3、通过连接获取语句对象
    //Statement是jdbc定一个的接口,表示sql语句
    //conn.createStatement():返回的是一个具体类对象,这个具体类实现了Statement 接口
    state = conn.createStatement();
    //4、通过语句对象执行具体的DQL语句对象,返回结果集对象
    //a、准备好sql语句
     //b、sql有不同的种类,Statement表示不同的sql语句,所以Statement上面有不同的方法执行不同的sql语句
     //我们通过调用Statement上面的executeQuery(sql)执行DQL语句,数据库返回结果集对象,
    String sql = "SELECT * FROM user_info WHERE role_id=2;";
    
    ResultSet res = state.executeQuery(sql);
    //5、遍历结果集,取出每条记录
    
    if (state.execute(sql)){
                    res = state.getResultSet();
                    //5、遍历结果集,取出每条记录
                    while(res.next()){
                        //res.next():a、判断结果集中是否有下一条数据,b、如果有下一行,迭代器移动到下一行
    
                        //通过字段在查询列表中位置取得字段信息,位置从1开始
                        String name1 = res.getString(2);
                        //通过该字段名称取得字段信息,这是首选方式,;字段名称不区分大小写
                        String name2 = res.getString("name");
                        int id1 = res.getInt(1);
                        int id2 = res.getInt("id");
                        Date create_time = res.getDate("create_time");
                        String account = res.getString("account");
                        String employee_number = res.getString("employee_number");
                        String email = res.getString("email");
                        System.out.println(id2+" ,"+name2+" ,"+account+" ,"+email+" ,"+employee_number+" ,"+create_time+" .");
                    }
                }
     //6、关闭数据库相关资源
                //在关闭的时候,需要反向关闭
                //异常处理:
                //          a、可以合着处理,也就是一个try处理多个异常,后面也可接多个catch
                //          b、可以分着处理,也就是分别用try....catch....处理每个异常
                //          c、何时分着?何时合着?当多个操作之间有联系的时候,应该合着处理;没有联系的时候,分着处理
                if (res!=null) {
                    try {
                        res.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
    
                if (state !=null) {
                    try {
                        state.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
    
                if (conn!=null) {
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }

    3.实例

    public class Test01 {
    
        public  static void main(String[] args){
            test01();
            test02();
        }
    
        private static void test02() {
    
            //1、注册数据库驱动,目的是为了让jvm可以识别mysql数据库驱动类
            //com.mysql.jdbc.Driver()是SUN公司对Driver接口的实现类型
            Connection conn=null;
            Statement state=null;
            ResultSet res=null;
    
            try {
                Driver driver = new com.mysql.jdbc.Driver();
                //通过驱动管理器注册驱动
                DriverManager.registerDriver(driver);
    
                //2、获取和数据库的连接
                //a、准备数据库相关资源
                String username="root";
                String password = "123456";
    
                //url:统一资源定位器,确定数据库服务器的信息
                //jdbc:是一套网络协议,jdbc:mysql:是jdbc协议下的mysql协议
                String url="jdbc:mysql://localhost:3306/test-csj";
                //b、获取和数据库的连接
                //Connection是jdbc定义的接口,表示和数据库的连接
                //DriverManager.getConnection返回的是一个具体类对象,这个具体类实现了Connection接口
                //这个具体类在驱动的jar文件中,
                conn = DriverManager.getConnection(url, username, password);
                //3、通过连接获取语句对象
                //Statement是jdbc定一个的接口,表示sql语句
                //conn.createStatement():返回的是一个具体类对象,这个具体类实现了Statement 接口
                state = conn.createStatement();
                //4、通过语句对象执行具体的DQL语句对象,返回结果集对象
                //a、准别好sql语句
                //b、sql有不同的种类,Statement表示不同的sql语句,所以Statement上面有不同的方法执行不同的sql语句
                //我们通过调用Statement上面的executeQuery(sql)执行DQL语句,数据库返回结果集对象,
                String sql = "SELECT * FROM user_info WHERE role_id=2;";
                String sql2= "INSERT INTO user_info VALUES(666,'chuchu','chuchu');";
                //调用Statement中的getResultSet()方法获取,
    
                if (state.execute(sql)){
                    res = state.getResultSet();
                    //5、遍历结果集,取出每条记录
                    while(res.next()){
                        //res.next():a、判断结果集中是否有下一条数据,b、如果有下一行,迭代器移动到下一行
    
                        //通过字段在查询列表中位置取得字段信息,位置从1开始
                        String name1 = res.getString(2);
                        //通过该字段名称取得字段信息,这是首选方式,;字段名称不区分大小写
                        String name2 = res.getString("name");
                        int id1 = res.getInt(1);
                        int id2 = res.getInt("id");
                        Date create_time = res.getDate("create_time");
                        String account = res.getString("account");
                        String employee_number = res.getString("employee_number");
                        String email = res.getString("email");
                        System.out.println(id2+" ,"+name2+" ,"+account+" ,"+email+" ,"+employee_number+" ,"+create_time+" .");
                    }
                }
                if (!state.execute(sql2)){
                    int i = state.executeUpdate(sql2);
                    System.out.println("i="+i);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                //6、关闭数据库相关资源
                //在关闭的时候,需要反向关闭
                //异常处理:
                //          a、可以合着处理,也就是一个try处理多个异常,后面也可接多个catch
                //          b、可以分着处理,也就是分别用try....catch....处理每个异常
                //          c、何时分着?何时合着?当多个操作之间有联系的时候,应该合着处理;没有联系的时候,分着处理
                if (res!=null) {
                    try {
                        res.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
    
                if (state !=null) {
                    try {
                        state.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
    
                if (conn!=null) {
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        private static void test01() {
            //1、注册数据库驱动,目的是为了让jvm可以识别mysql数据库驱动类
            //com.mysql.jdbc.Driver()是SUN公司对Driver接口的实现类型
            Connection conn=null;
            ResultSet res=null;
            Statement state=null;
    
            try {
                Driver driver = new com.mysql.jdbc.Driver();
                //通过驱动管理器注册驱动
                DriverManager.registerDriver(driver);
    
                //2、获取和数据库的连接
                //a、准备数据库相关资源
                String username="root";
                String password = "123456";
    
                //url:统一资源定位器,确定数据库服务器的信息
                //jdbc:是一套网络协议,jdbc:mysql:是jdbc协议下的mysql协议
    
                String url="jdbc:mysql://localhost:3306/test-csj";
    
                //b、获取和数据库的连接
                //Connection是jdbc定义的接口,表示和数据库的连接
                //DriverManager.getConnection返回的是一个具体类对象,这个具体类实现了Connection接口
                //这个具体类在驱动的jar文件中,
                conn = DriverManager.getConnection(url, username, password);
    
                //3、通过连接获取语句对象
                //Statement是jdbc定一个的接口,表示sql语句
                //conn.createStatement():返回的是一个具体类对象,这个具体类实现了Statement 接口
                state = conn.createStatement();
    
                //4、通过语句对象执行具体的DQL语句对象,返回结果集对象
                //a、准别好sql语句
                //b、sql有不同的种类,Statement表示不同的sql语句,所以Statement上面有不同的方法执行不同的sql语句
                //我们通过调用Statement上面的executeQuery(sql)执行DQL语句,数据库返回结果集对象,
                String sql = "SELECT * FROM user_info WHERE role_id=2;";
                res = state.executeQuery(sql);
                System.out.println(res);
    
                //5、遍历结果集,取出每条记录
                while(res.next()){
                    //res.next():a、判断结果集中是否有下一条数据,b、如果有下一行,迭代器移动到下一行
    
                    //通过字段在查询列表中位置取得字段信息,位置从1开始
                    String name1 = res.getString(2);
                    //通过该字段名称取得字段信息,这是首选方式,;字段名称不区分大小写
                    String name2 = res.getString("name");
    
                    int id1 = res.getInt(1);
                    int id2 = res.getInt("id");
    
                    Date create_time = res.getDate("create_time");
    
                    String account = res.getString("account");
    
                    String employee_number = res.getString("employee_number");
                    String email = res.getString("email");
                    System.out.println(id2+" ,"+name2+" ,"+account+" ,"+email+" ,"+employee_number+" ,"+create_time+" .");
    
                }
    
    
    
    
    
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                //6、关闭数据库相关资源
                //在关闭的时候,需要反向关闭
                //异常处理:
                //          a、可以合着处理,也就是一个try处理多个异常,后面也可接多个catch
                //          b、可以分着处理,也就是分别用try....catch....处理每个异常
                //          c、何时分着?何时合着?当多个操作之间有联系的时候,应该合着处理;没有联系的时候,分着处理
                if (res!=null) {
                    try {
                        res.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
    
                if (state !=null) {
                    try {
                        state.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
    
                if (conn!=null) {
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    二、由于代码中重复的代码很多,故进行封装

    1.新建uti l/jdbcUtil封装类(获取数据库连接对象,和关闭数据库)

    a、db.properties(为了读取文件,我们需要获取InputStream,注意下面这种方式是专门用来读取src下的文件的)
    user1 =root
    password1=123456
    url1=jdbc:mysql://localhost:3306/csjin
    className1=com.mysql.jdbc.Driver

    b、获取db.properties中的数据并通过流InputStream读取到代码中:

    //为了读取文件,我们需要获取InputStream,注意下面这种方式是专门用来读取src下的文件的
    //获取jdbcUtil类对应的Class对象
     Class<jdbcUtil> clasz = jdbcUtil.class;
     //通过Class对象获取ClassLoader类加载器对象
    ClassLoader loader = clasz.getClassLoader();
    //调用ClassLoader上面的方法获取inputStream
     InputStream in = loader.getResourceAsStream("db.properties");
    
     Properties pro = new Properties();
    
     //把pro对象和流连接起来
     pro.load(in);
    
    user = pro.getProperty("user1");
    password = pro.getProperty("password1");
    url = pro.getProperty("url1");
    className = pro.getProperty("className1");

    c、封装获取数据库连接

    /**
         * 注册驱动获取链接
         * @return
         */
        public static Connection getConnection() throws SQLException, ClassNotFoundException {
    
            Class.forName(className);//反射方法获取驱动
            Connection conn = DriverManager.getConnection(url, user, password);
            return conn;
    
        }

    其他方法获取数据库驱动:

    //方式一:我们创建new com.mysql.jdbc.Driver类对象的时候,JVM把这个类加载到内存
    //这样JVM就可以是被MySQL的数据库驱动了
    Driver driver = new com.mysql.jdbc.Driver();
    DriverManager.registerDriver(driver);
    
     //方式二:我们创建new com.mysql.jdbc.Driver类对象的时候,JVM把这个类加载到内存
    //这样JVM就可以是被MySQL的数据库驱动了
     Driver driver = new com.mysql.jdbc.Driver();可以不用执行DriverManager.registerDriver(driver);
    
     //方式三:使用反射方法,我们获取com.mysql.jdbc.Driver这个类对应的class类的时候,
     //JVM需要把com.mysql.jdbc.Driver自动加载到内存,这个JVM就可以识别数据库驱动了

    2.代码实例:

    import java.io.IOException;
    import java.io.InputStream;
    import java.sql.*;
    import java.util.Properties;
    
    public class jdbcUtil {
    
        private static String user;
        private static String password;
        private static String url;
        private static String className;
    
        static {
           /* //为了读取文件,我们需要获取InputStream,注意下面这种方式是专门用来读取src下的文件的
            //获取jdbcUtil类对应的Class对象
            Class<jdbcUtil> clasz = jdbcUtil.class;
            //通过Class对象获取ClassLoader类加载器对象
            ClassLoader loader = clasz.getClassLoader();
            //调用ClassLoader上面的方法获取inputStream
            InputStream in = loader.getResourceAsStream("db.properties");*/
    
            /**并上面三行代码*/
            InputStream in = jdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
            //为了方便的读取"db.properties"这张特殊格式的文件,创建一个java.util.properties类对象
            Properties pro = new Properties();
    
            try {
                //把pro对象和流连接起来
                pro.load(in);
    
                user = pro.getProperty("user1");
                password = pro.getProperty("password1");
                url = pro.getProperty("url1");
                className = pro.getProperty("className1");
            }catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 注册驱动获取链接
         * @return
         */
        public static Connection getConnection() throws SQLException, ClassNotFoundException {
    
            Class.forName(className);
            Connection conn = DriverManager.getConnection(url, user, password);
            return conn;
    
        }
    
        /**
         * 关闭数据库相关对象的方法
         */
        public static void closeDb(Connection conn, Statement state, ResultSet res){
    
            if (res!=null) {
                try {
                    res.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
            if (state !=null) {
                try {
                    state.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
            if (conn!=null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    3.调用封装的方法jdbcUtil,执行数据库sql

    import com.csjin.edu.TestJDBC.Test02.util.jdbcUtil;
    
    import java.sql.*;
    
    public class Test02 {
        
        public static void main(String[] args) throws SQLException, ClassNotFoundException {
    
            /**
             * 方式一:我们创建new com.mysql.jdbc.Driver类对象的时候,JVM把这个类加载到内存
             * 这样JVM就可以是被MySQL的数据库驱动了
             *  Driver driver = new com.mysql.jdbc.Driver();
             * DriverManager.registerDriver(driver);
             */
           test1();
            /**
             * 方式一:我们创建new com.mysql.jdbc.Driver类对象的时候,JVM把这个类加载到内存
             * 这样JVM就可以是被MySQL的数据库驱动了
             *  Driver driver = new com.mysql.jdbc.Driver();可以不用执行DriverManager.registerDriver(driver);
             */
            test2();
            /**
             * 使用反射方法,我们获取com.mysql.jdbc.Driver这个类对应的class类的时候,
             * JVM需要把com.mysql.jdbc.Driver自动加载到内存,这个JVM就可以识别数据库驱动了
             */
           test3();
    
            test4();
        }
    
        private static void test4() {
    
            Connection conn=null;
            Statement state=null;
            ResultSet res=null;
            try {
                conn = jdbcUtil.getConnection();
                state = conn.createStatement();
    
    
                String sql = "SELECT * FROM user_info WHERE role_id=2;";
                String sql2= "INSERT INTO user_info VALUES(222,'李','chu01','4b31a1d73cea9e6c432b59adc9eed725',1,2,111111,NULL,NULL,NULL,'aaaa@qq.com',NULL,NULL,0,'2020-03-20 00:00:00','2017-11-30 10:21:01','2017-11-30 10:21:01',1);";
    
                //如果第一个结果为 ResultSet 对象,则返回 true;如果其为更新计数或者不存在任何结果,则返回false
                if (!state.execute(sql2)){
                    //  来获取更新计数器
                    int count = state.getUpdateCount();
                    System.out.println("count ="+count);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                try {
                    jdbcUtil.closeDb(conn,state,res);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
        }
    
    
        private static void test3() throws ClassNotFoundException, SQLException {
    
            String className = "com.mysql.jdbc.Driver";
    
            Class.forName(className);
    
            String username="root";
            String password = "123456";
    
            //url:统一资源定位器,确定数据库服务器的信息
            //jdbc:是一套网络协议,jdbc:mysql:是jdbc协议下的mysql协议
            String url="jdbc:mysql://localhost:3306/test-csj";
            Connection conn = DriverManager.getConnection(url, username, password);
            if (conn!=null){
                System.out.println("驱动注册成功3!");
            }
        }
    
        private static void test2() throws SQLException {
            Driver driver = new com.mysql.jdbc.Driver();
            //通过驱动管理器注册驱动
            String username="root";
            String password = "123456";
    
            //url:统一资源定位器,确定数据库服务器的信息
            //jdbc:是一套网络协议,jdbc:mysql:是jdbc协议下的mysql协议
            String url="jdbc:mysql://localhost:3306/test-csj";
            Connection conn = DriverManager.getConnection(url, username, password);
            if (conn!=null){
                System.out.println("驱动注册成功2!");
            }
    
        }
    
        private static void test1() throws SQLException {
    
            Driver driver = new com.mysql.jdbc.Driver();
            //通过驱动管理器注册驱动
            DriverManager.registerDriver(driver);
            String username="root";
            String password = "123456";
    
            //url:统一资源定位器,确定数据库服务器的信息
            //jdbc:是一套网络协议,jdbc:mysql:是jdbc协议下的mysql协议
            String url="jdbc:mysql://localhost:3306/test-csj";
            Connection conn = DriverManager.getConnection(url, username, password);
            if (conn!=null){
                System.out.println("驱动注册成功1!");
            }
        }
    }

     三、如何防止SQl注入攻击

    /**
     * sql注入攻击:
     * SELECT * FROM users WHERE username='sss' AND `password`='ss' or 'x' = 'x';
     *
     * 如何避免sql注入攻击:
     * 使用PreparedStatement,PreparedStatement不需要sql拼接
     *
     * 比较PreparedStatement与Statement区别?
     * 1、Statement执行sql语句的时候,编译一次,执行一次,执行效率低
     *    PreparedStatemen执行sql语句的时候,编译一次,可以反复执行,效率高
     * 2、Statement执行sql语句需要拼接,有sql注入风险
     *    PreparedStatemen执行sql语句不需要拼接,使用占位符即可,可 避免sql注入
     *
     */

    1.从键盘获取用户名和密码,并将此方法封装成一个map类型的

    public class Test03 {
    
        public static Map<String,String> readkeyBoard(){
    
            Map<String,String> map = new HashMap<>();
    
            Scanner scan = new Scanner(System.in);
            System.out.println("请输入username,并回车:");
            String user = scan.nextLine();//scan.nextLine();以
    为标记读取一
            map.put("user",user);
    
            System.out.println("请输入password,并回车:");
            String password =  scan.nextLine();
            map.put("password",password);
    
            if (scan != null){
                scan.close();
            }
    
            return map;
        }

    2.利用登陆实例说明SQL注入,无防止

    密码只要输入:ss' or 'x' = 'x     即可登录成功,因为Statement,我们只能使用的sql拼接

    /**
         * 检查登录是否成功
         * @return
         */
        public static boolean login(){
    
            Map<String,String> map = readkeyBoard();
    
            Connection conn =null;
            Statement state =null;
            ResultSet res = null;
            boolean flag = false;
            try {
                conn = jdbcUtil.getConnection();
                state = conn.createStatement();
                String sql = "SELECT * FROM users WHERE username='"+map.get("user")+"' AND `password`='"+map.get("password")+"';";
                System.out.println(sql);
                res = state.executeQuery(sql);
                System.out.println(res);
                /**
                 * 查询结果中有数据
                 */
                if (res.next()){
                    flag=true;
                }
    
    
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
    
                jdbcUtil.closeDb(conn,state,res);
            }
            return flag;
        }
     public static void main(String[] args){
            if (login()){
                System.out.println("登录成功!");
            }else{
                System.out.println("无效的用户名密码");
            }
        }

    3.防止使用SQL注入,使用PreparedStatement,不实用拼接SQL,使用?占位符

    /**
         * 检查登录是否成功,防止SQL注入
         * @return
         */
        public static boolean loginSQL(){
    
            Map<String,String> map = readkeyBoard();
    
            Connection conn =null;
            PreparedStatement pstate =null;
            ResultSet res = null;
            boolean flag = false;
    
            try {
                conn = jdbcUtil.getConnection();
    
                //由于pstate对象需要把SQL预先编译到pstate对象中,所以我们需要提前准别一个SQL语句
                //注意:SQL语句中所有需要设置的内容,不论是什么类型,统统用一个占位符?表示,?表示需要设置的内容
                String sql = "SELECT * FROM users WHERE username =? AND password =? ";
    
                //把SQL语句编译到pstate对象中,并且返回pstate对象
                pstate = conn.prepareStatement(sql);
                //设置占位符具体值,注意从1开始
                pstate.setString(1,map.get("user"));
                pstate.setString(2,map.get("password"));
    
                //输出SQL语句
                System.out.println(sql);
                //由于SQL语句已经预先被预编译到pstate对象中,所以pstate.executeQuery()时候已经不需要SQL语句了
                res = pstate.executeQuery();
                System.out.println(res);
                /**
                 * 查询结果中有数据
                 */
                if (res.next()){
                    flag=true;
                }
                //输出SQL语句
                System.out.println(sql);
    
    
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
    
                jdbcUtil.closeDb(conn,pstate,res);
            }
            return flag;
        }
    
        public static void main(String[] args){
            if (loginSQL()){
                System.out.println("登录成功!");
            }else{
                System.out.println("无效的用户名密码");
            }
        }
    }

    四、其他案例

    import com.csjin.edu.TestJDBC.Test02.util.jdbcUtil;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class Test04 {
    
        public static void main(String[] args){
    
            //执行数据库DML
            test1();
            //执行数据DQL
            test2();
    
        }
    
        private static void test2() {
            Connection conn = null;
            PreparedStatement pstate = null;
            ResultSet res = null;
    
            try{
    
            conn = jdbcUtil.getConnection();
    
            String sql ="SELECT username,id,password FROM USERS where username=?";
    
            pstate = conn.prepareStatement(sql);
            pstate.setString(1,"admin");
    
            res = pstate.executeQuery();
            while (res.next()){
                String username = res.getString("username");
                int id = res.getInt("id");
                String password = res.getString("password");
                System.out.println("username ="+username+",id="+id+",password="+password);
            }
    
    
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            jdbcUtil.closeDb(conn,pstate,res);
        }
    
    
    }
    
        private static void test1() {
    
            Connection conn = null;
            PreparedStatement pstate = null;
            ResultSet res = null;
    
            try {
                conn = jdbcUtil.getConnection();
    
                String sql = "INSERT INTO USERS VALUES(?,?,?)";
    
                pstate = conn.prepareStatement(sql);
                pstate.setInt(1,2);
                pstate.setString(2,"chu01");
                pstate.setString(3,"123456");
    
                int i = pstate.executeUpdate();
                System.out.println("i="+i);
    
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                jdbcUtil.closeDb(conn,pstate,null);
            }
        }
    
    
    }

    五、使用PreparedStatement执行模糊查询

    package com.csjin.edu.TestJDBC.Test02;
    
    import com.csjin.edu.TestJDBC.Test02.util.jdbcUtil;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * 使用PreparedStatement执行模糊查询
     *
     */
    
    public class Test05 {
    
        public static void main(String[] args){
    
            //使用PreparedStatement执行模糊查询
            test1();
        }
    
        private static void test1() {
            Connection conn = null;
            PreparedStatement pstate = null;
            ResultSet res = null;
    
            try{
    
                conn = jdbcUtil.getConnection();
    
                String sql ="SELECT username,id,password FROM USERS where username like ?";
    
                pstate = conn.prepareStatement(sql);
                pstate.setString(1,"%dmi%");
    
                res = pstate.executeQuery();
                while (res.next()){
                    String username = res.getString("username");
                    int id = res.getInt("id");
                    String password = res.getString("password");
                    System.out.println("username ="+username+",id="+id+",password="+password);
                }
    
    
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                jdbcUtil.closeDb(conn,pstate,res);
            }
        }
    }

    六、数据库事务与JDBC事务

    /**
     * 数据库事物
     * Mysql中默认的事物管理方式是自动提交事务,mysql默认每个DML语句都会引起一个单独的事务,这个DML语句执行结束的时候,事务会自动提交
     *
     * 在数据库需要自动关闭事务:
     * 1、执行语句START TRANSACTION ,自动关闭事务,注意:这是本次关闭,在事务结束后,会恢复到默认自动提交
     * 2、在事务开始后,只要没有结束事务,无论执行多少个DML语句,这些DML语句都是隶属于同一个事务,事务中对数据库修改保存在内存中
     * 3、事务结束的两种方式:
     *    1、提交(COMMIT),结束事务,事务中对数据库的修改被永久的保存到数据库中
     *    2、回滚(ROLLBACK)结束事务,事务中的对数据库的修改被放弃
     *
     *
     *
     *在JDBC需要自动关闭事务:
     * 1、执行语句conn.setAutoCommit(false); ,自动关闭事务,注意:这是本次关闭,在事务结束后,会恢复到默认自动提交
     * 2、在事务开始后,只要没有结束事务,无论执行多少个DML语句,这些DML语句都是隶属于同一个事务,事务中对数据库修改保存在内存中
     * 3、事务结束的两种方式:
     *    1、提交(conn.commit()),结束事务,事务中对数据库的修改被永久的保存到数据库中
     *    2、回滚(conn.rollback)结束事务,事务中的对数据库的修改被放弃
     *
     */
    import com.csjin.edu.TestJDBC.Test02.util.jdbcUtil;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /**
     * 数据库事物
     * Mysql中默认的事物管理方式是自动提交事务,mysql默认每个DML语句都会引起一个单独的事务,这个DML语句执行结束的时候,事务会自动提交
     *
     * 在数据库需要自动关闭事务:
     * 1、执行语句START TRANSACTION ,自动关闭事务,注意:这是本次关闭,在事务结束后,会恢复到默认自动提交
     * 2、在事务开始后,只要没有结束事务,无论执行多少个DML语句,这些DML语句都是隶属于同一个事务,事务中对数据库修改保存在内存中
     * 3、事务结束的两种方式:
     *    1、提交(COMMIT),结束事务,事务中对数据库的修改被永久的保存到数据库中
     *    2、回滚(ROLLBACK)结束事务,事务中的对数据库的修改被放弃
     *
     *
     *
     *在JDBC需要自动关闭事务:
     * 1、执行语句conn.setAutoCommit(false); ,自动关闭事务,注意:这是本次关闭,在事务结束后,会恢复到默认自动提交
     * 2、在事务开始后,只要没有结束事务,无论执行多少个DML语句,这些DML语句都是隶属于同一个事务,事务中对数据库修改保存在内存中
     * 3、事务结束的两种方式:
     *    1、提交(conn.commit()),结束事务,事务中对数据库的修改被永久的保存到数据库中
     *    2、回滚(conn.rollback)结束事务,事务中的对数据库的修改被放弃
     *
     */
    public class Test06 {
    
        public static void main(String[] args){
    
            //非事务
            test1();
    
            //事务成功
            test2();
            //事务过程中失败,需手动执行回滚操作
            test3();
    
        }
    
        private static void test3() {
    
            Connection conn = null;
            PreparedStatement pstate = null;
            ResultSet res = null;
    
            try {
                conn = jdbcUtil.getConnection();
    
                //开启事务,关闭自动提交
                conn.setAutoCommit(false);
    
                String sql = "INSERT INTO users VALUES(?,?,?)";
    
                pstate = conn.prepareStatement(sql);
    
                // 设置并执行第一个DML语句
                pstate.setInt(1,2);
                pstate.setString(2,"chu02");
                pstate.setString(3,"123456");
    
                int i = pstate.executeUpdate();
                System.out.println("i="+i);
    
                // 设置并执行第二个DML语句
                pstate.setInt(1,3);
                pstate.setString(2,"chu03");
                pstate.setString(3,"123456");
    
                i = pstate.executeUpdate();
                System.out.println("i="+i);
    
    
                // 设置并执行第三个DML语句
                pstate.setInt(1,1);
                pstate.setString(2,"chu04");
                pstate.setString(3,"12345611111111111111111111111111111111111111111111111111111111111111111111111");
    
                i = pstate.executeUpdate();
                System.out.println("i="+i);
    
                //提交事务
                conn.commit();
    
            } catch (SQLException e) {
                System.err.println("事务SQLException异常信息如下:");
                e.printStackTrace();
                //手动回滚
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            } catch (ClassNotFoundException e) {
                System.out.println("事务ClassNotFoundException异常信息如下:");
                e.printStackTrace();
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            } finally {
                jdbcUtil.closeDb(conn,pstate,null);
            }
        }
    
        private static void test2() {
    
            Connection conn = null;
            PreparedStatement pstate = null;
            ResultSet res = null;
    
            try {
                conn = jdbcUtil.getConnection();
    
                //开启事务,关闭自动提交
                conn.setAutoCommit(false);
    
                String sql = "INSERT INTO users VALUES(?,?,?)";
    
                pstate = conn.prepareStatement(sql);
    
                // 设置并执行第一个DML语句
                pstate.setInt(1,2);
                pstate.setString(2,"chu02");
                pstate.setString(3,"123456");
    
                int i = pstate.executeUpdate();
                System.out.println("i="+i);
    
                // 设置并执行第二个DML语句
                pstate.setInt(1,3);
                pstate.setString(2,"chu03");
                pstate.setString(3,"123456");
    
                i = pstate.executeUpdate();
                System.out.println("i="+i);
    
    
                // 设置并执行第三个DML语句
                pstate.setInt(1,4);
                pstate.setString(2,"chu04");
                pstate.setString(3,"123456");
    
                i = pstate.executeUpdate();
                System.out.println("i="+i);
    
                //提交事务
                conn.commit();
    
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                jdbcUtil.closeDb(conn,pstate,null);
            }
        }
    
        private static void test1() {
    
            Connection conn = null;
            PreparedStatement pstate = null;
            ResultSet res = null;
    
            try {
                conn = jdbcUtil.getConnection();
    
                String sql = "INSERT INTO users VALUES(?,?,?)";
    
                pstate = conn.prepareStatement(sql);
    
                // 设置并执行第一个DML语句,并且自动提交
                pstate.setInt(1,2);
                pstate.setString(2,"chu02");
                pstate.setString(3,"123456");
    
                int i = pstate.executeUpdate();
                System.out.println("i="+i);
    
                // 设置并执行第二个DML语句,并且自动提交
                pstate.setInt(1,3);
                pstate.setString(2,"chu03");
                pstate.setString(3,"123456");
    
                i = pstate.executeUpdate();
                System.out.println("i="+i);
    
    
                // 设置并执行第三个DML语句,并且自动提交
                pstate.setInt(1,4);
                pstate.setString(2,"chu04");
                pstate.setString(3,"123456");
    
                i = pstate.executeUpdate();
                System.out.println("i="+i);
    
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                jdbcUtil.closeDb(conn,pstate,null);
            }
    
        }
    }

    七、在数据库与JDBC中使用行级锁

    /**
     * 在数据库中使用行级锁:
     * 1、执行数据库语句:start transaction ,关闭数据库自动提交
     * 2、执行语句:select * from users where id in(1,2) for update; 引起事务,启动行级锁,并且锁住id=1,2行
     *  注意:行级锁语句必须是主键作为查询条件,才能启动行级锁,否则是表级锁(数据库序列化的时候启动表)
     * 3、作用:启动行级锁只有当前事务才可以修改i=1,2这条记录,在当前事务中修改
     * 4、commit,结束事务,释放行级锁
     *
     */
    
    
    
    /**
     * 在jdbc中使用行级锁:
     * 1、执行语句:conn.setAutoCommit(false),关闭数据库自动提交
     * 2、执行语句:select * from users where id in(1,2) for update; 引起事务,启动行级锁,并且锁住id=1,2行
     *  注意:行级锁语句必须是主键作为查询条件,才能启动行级锁,否则是表级锁(数据库序列化的时候启动表)
     * 3、作用:启动行级锁只有当前事务才可以修改i=1,2这条记录,在当前事务中修改
     * 4、结束事务,释放行级锁
     *
     */

    示例代码:

    import com.csjin.edu.TestJDBC.Test02.util.jdbcUtil;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    
    /**
     * 在数据库中使用行级锁:
     * 1、执行数据库语句:start transaction ,关闭数据库自动提交
     * 2、执行语句:select * from users where id in(1,2) for update; 引起事务,启动行级锁,并且锁住id=1,2行
     *  注意:行级锁语句必须是主键作为查询条件,才能启动行级锁,否则是表级锁(数据库序列化的时候启动表)
     * 3、作用:启动行级锁只有当前事务才可以修改i=1,2这条记录,在当前事务中修改
     * 4、commit,结束事务,释放行级锁
     *
     */
    
    
    
    /**
     * 在jdbc中使用行级锁:
     * 1、执行语句:conn.setAutoCommit(false),关闭数据库自动提交
     * 2、执行语句:select * from users where id in(1,2) for update; 引起事务,启动行级锁,并且锁住id=1,2行
     *  注意:行级锁语句必须是主键作为查询条件,才能启动行级锁,否则是表级锁(数据库序列化的时候启动表)
     * 3、作用:启动行级锁只有当前事务才可以修改i=1,2这条记录,在当前事务中修改
     * 4、结束事务,释放行级锁
     *
     */
    
    public class Test07 {
    
        public static void main(String[] args){
            test1();
        }
    
        private static void test1() {
    
            Connection conn = null;
            PreparedStatement pstate = null;
            ResultSet res = null;
    
            try {
                conn = jdbcUtil.getConnection();
    
                //开启事务,关闭自动提交
                conn.setAutoCommit(false);
    
                String sql = "select * from users where id =? for update";
    
                pstate = conn.prepareStatement(sql);
                pstate.setInt(1,2);
    
                pstate.executeQuery();
    
                sql = "update users set password=1234567 where id=?";
                pstate = conn.prepareStatement(sql);
                pstate.setInt(1,2);
    
                int i = pstate.executeUpdate();
                System.out.println("i="+i);
    
    
                //提交事务
                conn.commit();
    
            } catch (SQLException e) {
                System.err.println("事务SQLException异常信息如下:");
                e.printStackTrace();
                //手动回滚
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            } catch (ClassNotFoundException e) {
                System.out.println("事务ClassNotFoundException异常信息如下:");
                e.printStackTrace();
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            } finally {
                jdbcUtil.closeDb(conn,pstate,null);
            }
        }
    }
  • 相关阅读:
    🔨FFmpeg 转换至 MP4 视频格式
    🔨Ubuntu Linux '门' '复' 显示不标准
    🔨Youtube-dl 开代理搭配 Aria2 多线程加速下载
    📔 如何用英语的思维来思考 How to THINK in English
    🚀 sublime 加速软件下载
    🚀 snap 代理
    🚀 Chocolatey 代理
    🔨 Deepin V20 软件及遇到的问题
    💿 npm 换源 (转载)
    🔨FFmpeg 合并视频
  • 原文地址:https://www.cnblogs.com/chushujin/p/11603052.html
Copyright © 2020-2023  润新知