JDBC-老杜-笔记

JDBC

1、JDBC是什么?

Java DataBase Connectivity(Java语言连接数据库)

2、JDBC的本质是什么?

JDBC是SUN公司制定的一套接口(interface)
	java.sql.*; (这个软件包下有很多接口。)

接口都有调用者和实现者。
面向接口调用、面向接口写实现类,这都属于面向接口编程。

为什么要面向接口编程?
	解耦合:降低程序的耦合度,提高程序的扩展力。
	多态机制就是非常典型的:面向抽象编程。(不要面向具体编程)
		建议:
			Animal a = new Cat();
			Animal a = new Dog();
			// 喂养的方法
			public void feed(Animal a){ // 面向父类型编程。
			
			}
		不建议:
			Dog d = new Dog();
			Cat c = new Cat();

思考:为什么SUN制定一套JDBC接口呢?
	因为每一个数据库的底层实现原理都不一样。
	Oracle数据库有自己的原理。
	MySQL数据库也有自己的原理。
	MS SqlServer数据库也有自己的原理。
	....
	每一个数据库产品都有自己独特的实现原理。

JDBC的本质到底是什么?
	一套接口。

3、JDBC开发前的准备工作,先从官网下载对应的驱动jar包,然后将其配置到环境变量classpath当中。

classpath=.;D:\course\JDBC\resources\MySql Connector Java 5.1.23\mysql-connector-java-5.1.23-bin.jar

以上的配置是针对于文本编辑器的方式开发,使用IDEA工具的时候,不需要配置以上的环境变量。
IDEA有自己的配置方式。

4、JDBC编程六步(需要背会)

第一步:注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库)

Class.forName("com.mysql.cj.jdbc.Driver");

第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道。)

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","123456");

第三步:获取数据库操作对象(专门执行sql语句的对象)

Statement stmt = conn.createStatement();

第四步:执行SQL语句(DQL DML…)

String sql = "select ename from emp order by ename desc ";
rs = stmt.executeQuery(sql);

第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。)

while (rs.next()){
            System.out.println(rs.getString("ename"));
        }

第六步:释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)

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

5、SQL注入

5.1、当前程序存在的问题:

用户名: fdsa
密码: fdsa’ or 1’=‘1’
登录成功
这种现象被称为SQL注入(安全隐患)。

5.2、导致SQL注入的根本原因是什么?

用户输入的信息中含有SQL语句的关键字,并且这些关键字参与SQL语句的编译过程,
导致sql语句的原意被扭曲,进而达到SQL注入。

5.3、解快SQL注入问题?

只要用户提供的信息不参与SQL语句的编译过程,问题就解决了。
即使用户提供的信息中含有SQL语句的关键字,但是没有参与编译,不起作用。
要想用户信息不参与sQL语句的编译,那么必须使用java.sql.Preparedstatement
Preparedstatement接口继承了java.sql.Statement
Preparedstatement是属于预编译的数据库操作对象。
Preparedstatement的原理是:预先对SQL语句的框架进行编译,然后再给SQL语句传"值”。

package com.wyy.jdbc;

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

public class test01 {
    public static void main(String[] args) {
        //JDBC code
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        boolean loginsuccess = false;

        try {
            // 第一步:注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库)
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道。)
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode",
                    "root","123456");
            //第三步:获取数据库操作对象(专门执行sql语句的对象)
            // SQL语句的框子。其中一个?,表示一个占位符,一个?将来接收一个“值”,注意:占位符不能使用单引号括起来。
            String sql = "select * from t_user where loginName = ? and loginPwd = ?";
            //程序执行到此处,会发送sql语句框子给DBMS,然后DBMS进行sql语句的预先编译。
            ps = conn.prepareStatement(sql);
            //给占位符传值
            Scanner sc = new Scanner(System.in);

//            String loginName = sc.next();
            String loginName = "zhangsan";
            // 给占位待2传值(第1个问号下标是1,第2个问号下标是2,JDBC中所有下标从1开始。)
            ps.setString(1,loginName);
//            String loginPwd = sc.next();
            String loginPwd = "123";
            ps.setString(2,loginPwd);
            // 第四步:执行SQL语句(DQL DML....)
            //第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。)
            rs = ps.executeQuery();
            if(rs.next()){
                loginsuccess = true;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //        第六步:释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)
            if (rs != null){
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (ps != null){
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
        System.out.println(loginsuccess ? "登陆成功" : "登录失败");
    }
}

5.4、对比一下statement和Preparedstatement?

Statement存在sql注入问题,Preparedstatement解决了SQL注入问题。
Statement是编译一次执行一次。Preparedstatement是编译一次可执行N次,效率更高。
Preparedstatement会在编译阶段做类型的安全检查。

package com.wyy.jdbc;

import java.sql.*;
import java.util.Scanner;

preparestatement
public class Test02 {
    public static void main(String[] args) {
        //用户在控制台输入desc是降序,asc是升序
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入desc(降序查看)或asc(升序查看)");
        System.out.println("请输入:");
        String keyword = sc.nextLine();

        //执行sql

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //1注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2获取连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","123456");
            //获取预编译的数据库操作对象
            String sql = "select ename from emp order by ename ? ";
            ps = conn.prepareStatement(sql);
            ps.setString(1,keyword);
            //执行sql
            rs = ps.executeQuery();
            //遍历结果集
            while (rs.next()){
                System.out.println(rs.getString("ename"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (rs != null){
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (ps != null){
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
        }

    }

6、JDBC事务机制:

  1、JDBC中的事务是自动提交的,什么是自动提交?
      只要执行任意一条DML语句,则自动提交一次。这是JDBC默认的事务行为。
      但是在实际的业务当中,通常都是N条DML语句共同联合才能完成的,必须
       保证他们这些DMI语句在同一个事务中同时成功或者同时失败。
   2、以下程序先来验证一下JDBc的事务是否是自动提交机制!
       测试结果: JDBC中 只要执行任意一条 DML语句,就提交一次
public class test05 {
  public static void main(String[] args) {
      Connection conn = null;
      PreparedStatement ps = null;
      ResultSet rs = null;

      try {
          Class.forName("com.mysql.cj.jdbc.Driver");
          conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","123456");
          String sql = "update dept set dname = ? where deptno = ?";
          ps = conn.prepareStatement(sql);
          ps.setString(1,"xpart");
          ps.setInt(2,30);
          int count = ps.executeUpdate();
          //重新传值
          ps.setString(1,"ypart");
          ps.setInt(2,20);
          count = ps.executeUpdate();
          System.out.println(count);
      } catch (Exception e) {
          e.printStackTrace();
      } finally {
          if (rs != null){
              try {
                  rs.close();
              } catch (SQLException throwables) {
                  throwables.printStackTrace();
              }
          }
          if (ps != null){
              try {
                  ps.close();
              } catch (SQLException throwables) {
                  throwables.printStackTrace();
              }
          }
          if (conn != null){
              try {
                  conn.close();
              } catch (SQLException throwables) {
                  throwables.printStackTrace();
              }
          }
      }

  }
}

重点三行代码
conn.setAutoCommit(false);
conn.commit();
conn.rollback();

package com.wyy.jdbc;

import java.sql.*;

/**
 * 重点三行代码
 * conn.setAutoCommit(false);
 * conn.commit();
 * conn.rollback();
 */
public class test06 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","123456");
            //将自动提交改为手动提交
            //=======开启事务=======
            conn.setAutoCommit(false);
            String sql = "update t_act set balance = ? where actno = ?";
            ps = conn.prepareStatement(sql);
            ps.setDouble(1,1000);
            ps.setInt(2,111);
            int count = ps.executeUpdate();

            //================
            //加了一个异常
            String s = null;
            s.toString();
            //================

            //重新传值
            ps = conn.prepareStatement(sql);
            ps.setDouble(1,1000);
            ps.setInt(2,222);
            count += ps.executeUpdate();
            System.out.println(count == 2 ? "success":"false");
            //程序走到这里证明没有异常
            //手动提交
            //=======提交事务=======
            conn.commit();
        } catch (Exception e) {
            //手动回滚
            if (conn != null){
                try {
                    //=======回滚事务=======
                    conn.rollback();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            e.printStackTrace();
        } finally {
            if (ps != null){
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
}

7、工具类

package com.wyy.jdbc.utills;

import java.sql.*;

/**
 * 工具类,简化编程
 */
public class DBUtil {
    private DBUtil(){

    }

    //静态方法
    static {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库连接对象
     * @return 连接对象
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {

        return DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","123456");
    }

    /**
     *  关闭资源
     * @param conn 连接对象
     * @param ps 数据库操作对象
     * @param rs 结果集
     */
    public static void close(Connection conn, Statement ps, ResultSet rs){
        if (rs != null){
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (ps != null){
            try {
                ps.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null){
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

package com.wyy.jdbc;

import com.wyy.jdbc.utills.DBUtil;

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

public class test07 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            conn = DBUtil.getConnection();
            //错误写法
//            String sql = "select ename from emp where ename like '_?%'";
//            ps = conn.prepareStatement(sql);
//            ps.setString(1,"A");

            String sql = "select ename from emp where ename like ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"_A%");
            rs = ps.executeQuery();
            while(rs.next()){
                System.out.println(rs.getString("ename"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DBUtil.close(conn,ps,rs);
        }

    }
}

8、锁

行级锁 – 悲观锁

select ename, job, sal from emp where job= ' MANAGER ' for update; 

在这里插入图片描述
事务1

package com.wyy.jdbc;

import com.wyy.jdbc.utills.DBUtil;

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

/**
 * 这个程序开启一个事务,这个事务专门进行查询,并且使用行级锁/悲观锁,锁住相关的记录。
 */
public class Test08 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            conn = DBUtil.getConnection();
            //开启事务
            conn.setAutoCommit(false);

            String sql = "select ename,job,sal from emp where job = ? for update";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"MANAGER");
            rs = ps.executeQuery();
            while(rs.next()){
                System.out.println(rs.getString("ename")+","+rs.getString("job")
                +","+rs.getDouble("sal"));
            }
            //提价事务 = 事务结束
            conn.commit();
        } catch (SQLException throwables) {
            if (conn != null){
                try {
                    conn.rollback();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            throwables.printStackTrace();
        }finally {
            DBUtil.close(conn,ps,rs);
        }
    }
}

事务2

package com.wyy.jdbc;

import com.wyy.jdbc.utills.DBUtil;

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

public class test09 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;

        try {
            conn = DBUtil.getConnection();
            conn.setAutoCommit(false);

            String sql = "update emp set sal = sal * 1.1 where job = ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"MANAGER");
            int count = ps.executeUpdate();
            System.out.println(count);
            conn.commit();
        } catch (SQLException throwables) {
            if(conn!= null){
                try {
                    conn.rollback();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            throwables.printStackTrace();
        }finally {
            DBUtil.close(conn,ps,null);
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值