Java学习--JDBC模块

JDBC


  • java.sql.*

编程六步

  1. 注册驱动
  2. 获取连接属于(属于进程间的通信,使用后一定要关闭)
  3. 获取数据库操作对象
  4. 执行SQL语句
  5. 处理查询结果集(只有第四步执行是select语句,才需要处理)
  6. 释放资源
package Sql;

import java.sql.*;
import java.util.ResourceBundle;


public class Test01 {
    public static void main (String[] args) throws SQLException {
        //获取配置文件信息
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        String driver = bundle.getString("driver");
        String url = bundle .getString("url") ;
        String user = bundle .getString("user") ;
        String password = bundle .getString ("password") ;

        Connection conn = null;
        Statement stmt = null;

        try {
            //1. 注册驱动
            Class.forName(driver);

            //2. 获取连接属于(属于进程间的通信,使用后一定要关闭)
            conn = DriverManager.getConnection(url, user, password);
            //3. 获取数据库操作对象
            stmt = conn.createStatement();
            //4. 执行SQL语句
            String sql = "update beauty set name = 132 where id =1;";
            int count = stmt.executeUpdate(sql);
            System.out.println(count == 1? "修改成功":"修改失败");
            //5. 处理查询结果集(只有第四步执行是select语句,才需要处理)
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            //6. 释放资源
            if (stmt != null){
                stmt.close();
            }
            if (conn != null){
                conn.close();
            }
            
        }

    }
}

处理查询结果
  1. int eccuteUpdate(String sql); 可传入insert,delate,update 返回增删减了多少行数据
  2. ResultSet excuteQuery(String sql); 专门执行select语句
    返回ResultSet对象

JDBC数据,是从1开始

ResultSet对象常用方法

  1. boolean next()
    throws SQLException
    将光标从当前位置向前移一行。 ResultSet 光标最初位于第一行之前;第一次调用 next 方法使第一行成为当前行;第二次调用使第二行成为当前行,依此类推。

  2. String getString(int columnIndex)
    //当使用列名查询时,列名是查询结果集的列名称
    throws SQLException
    以 Java 编程语言中 String 的形式获取此 ResultSet 对象的当前行中指定列的值。

  3. boolean wasNull()
    throws SQLException
    报告最后一个读取的列是否具有值 SQL NULL。注意,必须首先对列调用一个获取方法尝试读取其值,然后调用 wasNull 方法查看读取的值是否为 SQL NULL。

  4. getInt
    int getInt(int columnIndex)
    throws SQLException
    以 Java 编程语言中 int 的形式获取此 ResultSet 对象的当前行中指定列的值。

package Sql;

import java.sql.*;
import java.util.ResourceBundle;


public class Test01 {
    public static void main (String[] args) throws SQLException {
        //获取配置文件信息
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        String driver = bundle.getString("driver");
        String url = bundle .getString("url") ;
        String user = bundle .getString("user") ;
        String password = bundle .getString ("password") ;

        Connection conn = null;
        Statement stmt = null;

        ResultSet rs = null;

        try {
            //1. 注册驱动
            Class.forName(driver);

            //2. 获取连接属于(属于进程间的通信,使用后一定要关闭)
            conn = DriverManager.getConnection(url, user, password);
            //3. 获取数据库操作对象
            stmt = conn.createStatement();
            //4. 执行SQL语句
            String sql = "select * from beauty;";
            rs = stmt.executeQuery(sql);
            //5. 处理查询结果集(只有第四步执行是select语句,才需要处理)
            boolean flag1 = rs.next();
            if (flag1){
            	/*
				String id = rs.getString(1);
                String name = rs.getString(2);
                String sex = rs.getString(3);
				*/
                String id = rs.getString("id");
           
                String name = rs.getString("name");
                String sex = rs.getString("sex");
                System.out.println(id + name + sex);
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            //6. 释放资源
            if (rs != null){
                rs.close();
            }
            if (stmt != null){
                stmt.close();
            }
            if (conn != null){
                conn.close();
            }

        }

    }
}


SQL注入
package Sql;
/*
实现功能:
1、需求:模拟用户登录功能的实现。,
2、业务描述:
程序运行的时候,提供一个输入的入口,可以让用户输入用户名和密码
用户输入用户名和密码之后,提交信息,java程序收集到用户信息
Java程序连接数据库验证用户名和密码是否合法
合法:显示登录成功
不合法:显示登录失败
3、数据准备
    建模工具:PowerDesigner
4、sql注入
    导致sQL注入的根本原因是什么?
用户输入的信息中含有 sq1语句的关键字,并且这些关键字参与sq1语句的编译过程,
导致sq1语句的原意被扭曲,进而达到sql注入。

*/

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Scanner;

public class UserTest {
    public static void main (String[] args){
        //初始化一个界面
        Map<String,String>userLoginInfo = initUI();
        //验证用户名
        boolean loginSuccess = login(userLoginInfo);

        //输出结果
        System.out.println(loginSuccess?"登陆成功":"登陆失败");

    }

    private static boolean login(Map<String, String> userLoginInfo) {

        boolean loginSuccess = false;

        String loginName = userLoginInfo.get("loginName");
        String loginPwd = userLoginInfo.get("loginPwd");

        //JDBC代码
        ResourceBundle bundle = ResourceBundle.getBundle("user");
        String driver = bundle.getString("driver");
        String url = bundle .getString("url") ;
        String user = bundle .getString("user") ;
        String password = bundle .getString ("password") ;
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;


        try {
            //1. 注册驱动
            Class.forName(driver);

            //2. 获取连接属于(属于进程间的通信,使用后一定要关闭)
            conn = DriverManager.getConnection(url, user, password);
            //3. 获取数据库操作对象
            stmt = conn.createStatement();
            //4. 执行SQL语句
            String sql = "select * from user where username = '"+loginName+"'" +
                    "and userPwd = '"+loginPwd+"';";

            rs = stmt.executeQuery(sql);
            //5. 处理查询结果集(只有第四步执行是select语句,才需要处理)
            if (rs.next()){
                //登陆成功
                loginSuccess = true;

            }else {
                loginSuccess = false;
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        finally {
            //6. 释放资源
            if (rs != null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

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

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

            }

        }

        return loginSuccess;

    }

    /**
     * 初始化界面
     * @return
     */
    private static Map<String, String> initUI() {
        Scanner s = new Scanner(System.in);
        System.out.println("欢迎登陆");
        System.out.print("用户名:");
        String loginName = s.nextLine();
        System.out.print("用户密码:");
        String loginPwd = s.nextLine();
        Map<String,String> userloginInfo = new HashMap<>();
        userloginInfo.put("loginName", loginName);
        userloginInfo.put("loginPwd", loginPwd);
        return userloginInfo;
    }


}


使用preparedstatement

package Sql;

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Scanner;

/*
* 解决sql注入问题
*   只要用户提供过的信息不参与sql语句的编译过程,问题就解决了
*   只要用户提供的信息含有sql语句的关键字,但没参与编译,不起作用
*   java.sql.PreparedStatement预编译数据库操作对象,
*   预先对sql语句框架进行编译,然后再给sql语句传值
* */

public class userTest02 {
    public static void main (String[] args){
        //初始化一个界面
        Map<String,String> userLoginInfo = initUI();
        //验证用户名
        boolean loginSuccess = login(userLoginInfo);

        //输出结果
        System.out.println(loginSuccess?"登陆成功":"登陆失败");

    }

    private static boolean login(Map<String, String> userLoginInfo) {

        boolean loginSuccess = false;

        String loginName = userLoginInfo.get("loginName");
        String loginPwd = userLoginInfo.get("loginPwd");

        //JDBC代码
        ResourceBundle bundle = ResourceBundle.getBundle("user");
        String driver = bundle.getString("driver");
        String url = bundle .getString("url") ;
        String user = bundle .getString("user") ;
        String password = bundle .getString ("password") ;

        Connection conn = null;

        PreparedStatement ps = null;
        ResultSet rs = null;


        try {
            //1. 注册驱动
            Class.forName(driver);

            //2. 获取连接属于(属于进程间的通信,使用后一定要关闭)
            conn = DriverManager.getConnection(url, user, password);
            //3. 获取预编译的数据库操作对象
            // sql语句的框架,其中一个? 便是一个占位符,一个?接收一个值
            String sql = "select * from user where username = ? and userPwd = ? ;";
            ps = conn.prepareStatement(sql);
            //4. 给占位符传值,第一个?问号下标是1
            ps.setString(1, loginName);
            ps.setString(2, loginPwd);


            rs = ps.executeQuery(sql);
            //5. 处理查询结果集(只有第四步执行是select语句,才需要处理)
            if (rs.next()){
                //登陆成功
                loginSuccess = true;

            }else {
                loginSuccess = false;
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        finally {
            //6. 释放资源
            if (rs != null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

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

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

            }

        }

        return loginSuccess;

    }

    /**
     * 初始化界面
     * @return
     */
    private static Map<String, String> initUI() {
        Scanner s = new Scanner(System.in);
        System.out.println("欢迎登陆");
        System.out.print("用户名:");
        String loginName = s.nextLine();
        System.out.print("用户密码:");
        String loginPwd = s.nextLine();
        Map<String,String> userloginInfo = new HashMap<>();
        userloginInfo.put("loginName", loginName);
        userloginInfo.put("loginPwd", loginPwd);
        return userloginInfo;
    }
}

使用statement的场景
  • 查询要进行数据升降排序
  • 需要传关键字进去编译

JDBC事务

  • 默认是执行一次DML语句,则自动提交一次
package Sql;

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Scanner;

public class Test {
    public static void main (String[] args){
        //JDBC代码
        ResourceBundle bundle = ResourceBundle.getBundle("user");
        String driver = bundle.getString("driver");
        String url = bundle .getString("url") ;
        String user = bundle .getString("user") ;
        String password = bundle .getString ("password") ;

        Connection conn = null;

        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            //1. 注册驱动
            Class.forName(driver);

            //2. 获取连接属于(属于进程间的通信,使用后一定要关闭)
            conn = DriverManager.getConnection(url, user, password);

            // 将自动提交设为自动提交,开启事务
            conn.setAutoCommit(false);

            //3. 获取预编译的数据库操作对象
            // sql语句的框架,其中一个? 便是一个占位符,一个?接收一个值
            String sql = "update t_act  set balance = ?where act_no =?;";
            ps = conn.prepareStatement(sql);
            //4. 给占位符传值,第一个?问号下标是1
            ps.setDouble(1,10000);
            ps.setInt(2, 111);
            int count = ps.executeUpdate();

            ps.setDouble(1,10000);
            ps.setInt(2, 222);
            count += ps.executeUpdate();

            System.out.println(count == 2? "转账成功":"转账失败");

            //5. 提交事务

            conn.commit();

        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
            if (conn != null){//事务回滚
                try {
                    conn.rollback();
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            }
        }
        finally {
            //6. 释放资源
            if (rs != null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

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

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

            }

        }

    }
}

  1. 行级锁(悲观锁)
    当select语句后加for update;后,查询的数据记录,在当前的事务还没结束前,别的事务无法对上述的数据修改

  2. 乐观锁,支持并发,事务不需要排队。还需要一个版本号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值