JDBC入门学习和JDBC的事务

一.JDBC是什么,它有什么作用

当我们学习了Java和MySQL数据库后,如何通过Java代码去操作数据库内的数据呢?这就用到了JDBC,JDBC是SUN公司提供的一套接口,面向接口编程给我们带来了很大的遍历,只需要不同的数据库厂商对该接口进行实现即可,当不同数据库厂商实现了JDBC接口后,我们只需要调用接口内的方法,而不需要关注不同数据库厂商底层的实现方法,带来了很大的遍历。

编写代码模拟JDBC的实现过程

public interface JDBCTest {
    //模拟SUN公司提供的JDBC接口
    public void getConn();
}

/*****************************************************/
public class MySQLTest implements JDBCTest{
    //模拟MySQL厂商的底层实现
    @Override
    public void getConn() {
        System.out.println("连接到MySQL数据库");
    }
}

/******************************************************/
public class OracleTest implements JDBCTest {
    //模拟Oracle厂商的底层实现
    @Override
    public void getConn() {
        System.out.println("连接到Oracle数据库");
    }
}
/*******************************************************/
public class ConnMySQL {
    public static void main(String[] args) {
        //模拟我们程序员对接口进行调用
        JDBCTest jdbcTest1 = new MySQLTest();
        JDBCTest jdbcTest2 = new OracleTest();
    }
}

二.JDBC的基本应用

JDBC的实现,主要分为以下几个步骤

1.注册DriverManager驱动

2.获取与数据库的链接Connection

3.创建执行SQL语句的对象Statement

4.执行SQL语句,如果是查询语句的话,返回结果集ResultSet

5.处理结果集ResultSet

6.关闭连接,由小到大 ResultSet,Statement,Connection

代码如下

public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1.注册驱动 注意这里的Driver()包导的是mysql厂商提供的包
        DriverManager.registerDriver(new Driver());
        //2.获得连接 三个参数分别为数据库的url 数据库用户名 数据库密码
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql", "root", "123456");
        //3.创建执行SQL语句的Statement对象
        Statement st = conn.createStatement();
        //4.执行SQL语句
        ResultSet rs = st.executeQuery("SELECT * FROM cl");
        //5.处理结果集
        while (rs.next()){
            //下标是从1开始的,也可以根据字段名取出数据
            int id = rs.getInt(1);
            //int id2 = rs.getInt("cid");
            System.out.println(id);
        }
        //6.关闭连接,从小到大
        rs.close();
        st.close();
        conn.close();
    }
}

 三.代码中异常的处理以及工具类和配置文件的封装

由于在上述代码中,没有对异常进行处理,直接将异常抛出给调用它的方法,所以我们自己进行处理,而且在连接的获取和URL,姓名,密码的过程中,代码是固定的,所以我们将它单独封装出来,这样不仅会降低程序的耦合度,也大大降低了程序的复杂度。

/********************配置文件db.properties************************/
DRIVERNAME=com.mysql.jdbc.Driver
URL=jdbc:mysql://localhost:3306/mysql
USERNAME=root
PASSWORD=123456
/********************封装工具类JdbcUtils**************************/
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {
   public static String drivername ;
    public static String url ;
    public static String userName ;
    public static String passWord ;
    static {
        Properties properties = new Properties();
        InputStream in = JDBCDemo2.class.getClassLoader().getResourceAsStream("Resources/db.properties");
        try {
            properties.load(in);
            drivername = properties.getProperty("DRIVERNAME");
            url = properties.getProperty("URL");
            userName = properties.getProperty("userName");
            passWord = properties.getProperty("passWord");
            //为什么使用反射而不是DriverMangager.Register() 因为后者会注册两次驱动
            Class.forName(drivername);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    //这个方法用来获得与数据库的连接
    public static Connection getConn() throws Exception {
        return  DriverManager.getConnection(url, userName, passWord);
    }

    public  static void release(ResultSet rs,Statement st,Connection conn){
        try {
            if(rs!=null){
                rs.close();
                rs=null;
                //垃圾回收器会马上回收
            }
        }catch (Exception e ){
            e.printStackTrace();
        }
        try {
            if(st!=null){
                st.close();
                st=null;
                //垃圾回收器会马上回收
            }
        }catch (Exception e ){
            e.printStackTrace();
        }
        try {
            if(conn!=null){
                conn.close();
                conn=null;
                //垃圾回收器会马上回收
            }
        }catch (Exception e ){
            e.printStackTrace();
        }

    }
}
/********************主类JdbcDemo2**************************/
import com.mysql.jdbc.Driver;

import javax.sql.rowset.JdbcRowSet;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;


public class JDBCDemo2 {
    public static void main(String[] args)  {
        Connection conn =null;
        Statement st = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtils.getConn();
            st = conn.createStatement();
            rs = st.executeQuery("SELECT * FROM cl");
            while (rs.next()){
                int id = rs.getInt(1);
            }
            JDBCUtils.release(rs,st,conn);
        }catch (Exception e ){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(rs,st,conn);
        }




    }
}

 四.登录案例和SQL注入现象的演示以及解决

登录案例

用JDBC模拟一个登录的案例,首先数据库中要有一个用户信息表。

CREATE TABLE user_info(

name varchar(255),

password varchar(255)

);

INSERT INTO user_info VALUES('zs','123456'),('ls','888888');

主类代码如下:

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

public class JDBCDemo3 {
    public static void main(String[] args) {
        Connection conn =null;
        Statement st =null;
        ResultSet rs = null;
        try {
            //1.获取与数据库的连接
            conn = JDBCUtils.getConn();
            //2.让用户自己输入账号和密码,并接收为参数
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入用户名");
            String userName = sc.nextLine();
            System.out.println("请输入密码");
            String passWord = sc.nextLine();
            //3.获得SQL语句的执行对象
            st = conn.createStatement();

            //字符串类型要自己加单引号,st不能自动添加
            rs = st.executeQuery("SELECT * FROM user_info WHERE name='" + userName + "AND password=" + passWord + "'");
            if (rs.next()){
                System.out.println("登陆成功");
            }else {
                System.out.println("登陆失败");
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(rs,st,conn);
        }


    }
}

SQL注入现象

在上述的代码中,如果我们在输入密码时输入'1asd' or '1' ='1  依然会登陆成功,效果如下图

首先我们要知道产生这个现象的原因是什么,当我们输入的字符串拼接到SQL语句上时,是下面这样的

SELECT * FROM user_info WHERE name='asd' AND password='lasd' or '1'='1'

我们可以看出来,产生SQL注入现象的原因有两个

1.我们输入的字符串中有SQL关键字

2.更重要的,DBMS将我们输入的关键字编译了

解决方法如下:

既然我们的关键字被DBMS编译了,我们就解决这个问题,把Statement对象换成PreparedStatement

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

public class JDBCDemo3 {
    public static void main(String[] args) {
        Connection conn =null;
        PreparedStatement pst =null;
        ResultSet rs = null;
        try {
            //1.获取与数据库的连接
            conn = JDBCUtils.getConn();
            //2.让用户自己输入账号和密码,并接收为参数
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入用户名");
            String userName = sc.nextLine();
            System.out.println("请输入密码");
            String passWord = sc.nextLine();
            //3.获得SQL语句的执行对象
            //Statement st = conn.createStatement();
            //PreparedStatement会对SQL语句进行预编译
            pst = conn.prepareStatement("SELECT * FROM user_info WHERE name=? AND password=?");
            //设置账号和密码,下标从1开始
            //如果是字符串类型的话,会在赋值的时候自动加单引号
            pst.setString(1,userName);
            pst.setString(2,passWord);
            //执行
            rs = pst.executeQuery();
            //字符串类型要自己加单引号,st不能自动添加
            //ResultSet rs = st.executeQuery("SELECT * FROM user_info WHERE name='" + userName + "AND password=" + passWord + "'");
            if (rs.next()){
                System.out.println("登陆成功");
            }else {
                System.out.println("登陆失败");
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(rs,pst,conn);
        }


    }
}

 五.JDBC演示MySQL的事务

数据库中的事务是指对数据库执行一批操作,这些操作最终要么全部执行成功,要么全部

失败,不会存在部分成功的情况。

举个例子

⽐如A用户给B用户转账100操作,过程如下:

1.从A账户扣100

2.给B账户加100

如果在事务的支持下,上⾯最终只有2种结果:

1. 操作成功:A账户减少100;B账户增加100

2. 操作失败:A、B两个账户都没有发⽣变化

如果没有事务的支持,可能出现错:A账户减少了100,此时系统挂了,导致B账户没有加

上100,A账户凭空少了100

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值