JavaWEB---JDBC

1、jdbc简介

JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统的。通用的SQL数据库存取和操作的公共接口(一组API),定义了用来采访数据库的标准java类库,使用这个类库可以以一种标准的方法,方便的访问数据库资源(java.sql包中)

JDBC为访问不同的数据库提供了一种统一的途径,JDBC对开发组屏蔽了一些细节问题。

JDBC的目标是使应用程序开发人员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。

JDBC包括两个层次

  1. 面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果集)

  2. 面向数据库API:Java Driver API,供开发数开发数据库驱动程序

主要概念

DriverManager(java.sql.DriverManager)

装载驱动程序,管理应用程序与驱动程序之间的连接

Driver(由驱动程序开放式提供)

将应用程序的API请求转换为特定的数据库请求

Connection(java.sql.Connection)

将应用程序连接到特定的数据库

Statement

在一个给定的连接中,用于执行一个数据库SQL语句u

ResultSet

SQL语句完成 后,返回的数据库结果集(包括行、列)

2、jdbc操作

1>添加jar文件,测试jar文件是否添加成功

2>加载驱动

  Class.forName("com.mysql.cj.jdbc.Driver");//加载类

3>获取与数据库的链接

String url="jdbc:mysql:///oa?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true";
String username = "root";
String pwd="123456";
Connection connection =  DriverManager.getConnection(url,username,pwd);

链接数据库需要提供什么? 链接的url 用户名 密码

5.x 链接数据库的url jdbc:mysql://localhost:3306/test 如果是本机,端口号没改变 jdbc:mysql:///test

8.x url

jdbc:mysql:///test?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true

4>创建通道,发送sql指令

 Statement stmt =  connection.createStatement();

创建Statement 通过改对象发送sql指令

1、execute  该方法可以发送select或者 insert update delete语句,如果是增删改方法 返回false,如果是select语句返回true
            该方法不常用
2、executeUpdate  返回sql语句影响的行数
3、exexuteQuery   返回结果集

5>需要处理结果集

ResultSet

 String sql="SELECT deptid did,deptname dname FROM dept";
            rs =  stmt.executeQuery(sql);
            while(rs.next()){
              int id =   rs.getInt("did");//通过查询结果的列名获取数据
              int id1 =   rs.getInt(1);//通过列序号,从1开始
                System.out.println(id+"---"+id1);
            }

6>关闭资源

 public static void main(String[] args) {
        Connection connection = null;
        Statement stmt = null;
        try {
            Class.forName(JDBCUtils.DRIVER);
            connection =  DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD);
            stmt  =  connection.createStatement();
            String sql="delete from dept where deptid=3";
            int rows =  stmt.executeUpdate(sql);
            System.out.println(rows);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            try {
                if(stmt!=null){
                    stmt.close();
                }
                if(connection!=null){
                    connection.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            Class.forName(JDBCUtils.DRIVER);
            conn =  DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD);
            stmt =  conn.createStatement();
          //  String sql="select * from dept";
            String sql="SELECT deptid did,deptname dname FROM dept";
            rs =  stmt.executeQuery(sql);
            while(rs.next()){
              int id =   rs.getInt("did");//通过查询结果的列名获取数据
              int id1 =   rs.getInt(1);//通过列序号,从1开始
                System.out.println(id+"---"+id1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(rs!=null){
                    rs.close();
                }
                if(stmt!=null){
                    stmt.close();
                }
                if(conn!=null){
                    conn.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

3、sql注入与PreparedStatement

1、sql注入的含义

通过拼接特殊sql语句,获取到不该获取的数据

String sql="SELECT * FROM users WHERE uname='"+uname+"' AND upwd='"+upwd+"'";
//传入值的时候,密码传递的结果是   ' OR '1'='1     刚好拼接出一个  or '1'='1'  恒成立的条件 获取到了所有的数据
//SELECT * FROM users WHERE uname='aa' AND upwd='' OR '1'='1'
 public static void main(String[] args) {

        String inname ="aa";
        String inpwd = "' OR '1'='1";
        Connection connection = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            Class.forName(JDBCUtils.DRIVER);
            connection =   DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD);
            stmt =  connection.createStatement();
            String sql="SELECT * FROM users WHERE uname='"+inname+"' AND upwd='"+inpwd+"'";
            System.out.println(sql);
            rs =  stmt.executeQuery(sql);
            while (rs.next()){
              int id =   rs.getInt("uid");
              String  name =   rs.getString("uname");
              String  pwd =   rs.getString("upwd");
              System.out.println(id+"\t"+name+"\t"+pwd);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
          ....
        //输入用户名和密码获取信息
    }

如果避免,java提供了PreparedStatement 防止sql注入:在使用PreparedStatement的时候,sql语句中的参数,全部通过占位符的方式来使用,给占位符赋值

....   
String sql="SELECT * FROM users WHERE uname=? and upwd=? ";
..... 
           pstmt =  connection.prepareStatement(sql);
           pstmt.setString(1,inname);
           pstmt.setString(2,inpwd);

           rs =  pstmt.executeQuery();
public static void main(String[] args) {

        String inname ="zs";
   //     String inpwd = "' OR '1'='1";
        String inpwd="147258";
        Connection connection = null;
        PreparedStatement  pstmt = null;
        ResultSet rs = null;
        String sql="SELECT * FROM users WHERE uname=? and upwd=? ";
      //  String sql="SELECT * FROM users WHERE uname='"+inname+"' and upwd='"+inpwd+"' ";
        try {
            Class.forName(JDBCUtils.DRIVER);
            connection =   DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD);

           pstmt =  connection.prepareStatement(sql);
           pstmt.setString(1,inname);
           pstmt.setString(2,inpwd);

            rs =  pstmt.executeQuery();
            while (rs.next()){
              int id =   rs.getInt("uid");
              String  name =   rs.getString("uname");
              String  pwd =   rs.getString("upwd");
              System.out.println(id+"\t"+name+"\t"+pwd);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ....
        }

        //输入用户名和密码获取信息
    }
Connection connection = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            Class.forName(JDBCUtils.DRIVER);
            connection =  DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD);
            String sql="INSERT INTO dept VALUES(NULL,?,?,?)";
            pstmt  =  connection.prepareStatement(sql);
            pstmt.setString(1,"采购部");
            pstmt.setString(2,"pstmt实现");
            pstmt.setInt(3,5);
            int rows =   pstmt.executeUpdate();
            System.out.println(rows);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(connection,pstmt,rs);
        }

日期类型的处理

Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务。

事务

public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        Connection conn = null;
        Statement stmt = null;
        System.out.println("请输入一个数");
        int num = input.nextInt();//如果输入的是0 则代码执行不成功
        try {
            Class.forName(JDBCUtils.DRIVER);
            conn =  DriverManager.getConnection(JDBCUtils.URL,JDBCUtils.USERNAME,JDBCUtils.PASSWORD);
            conn.setAutoCommit(false);//手动事务
            stmt =   conn.createStatement();
            stmt.executeUpdate("INSERT INTO dept VALUES(NULL,'ceshinew2','xx',0)");
            if(num==0){
                throw new RuntimeException("数据添加失败");
            }

            stmt.executeUpdate("INSERT INTO dept VALUES(NULL,'ceshinew3','xx',0)");
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        } finally {
            JDBCUtils.close(conn,stmt,null);
        }
    }

打点事务

public  static  void test01(){
        JDBCUtils jdbcUtils = new JDBCUtils();
        Connection connection = null;
        Statement stmt = null;
        Savepoint sp = null;
        Scanner input = new Scanner(System.in);
        System.out.println("请输入一个数");
        int num = input.nextInt();
        try {
            connection  =  jdbcUtils.getConnection();
            connection.setAutoCommit(false);
            stmt = connection.createStatement();
            stmt.executeUpdate("update account set balance=balance-50 where accid=1");
            sp = connection.setSavepoint();
            stmt.executeUpdate("update account set balance=balance-5000 where accid=1");
            if(num==2){
              throw  new RuntimeException("失败了");
            }
            stmt.executeUpdate("update account set balance=balance+5000 where accid=2");

        } catch (SQLException throwables) {
             System.err.println("发生了数据库异常");
            try {
                connection.rollback(sp);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }catch (RuntimeException e){
           // e.printStackTrace();
            System.err.println("发生未知的异常:"+e.getMessage());
            try {
                connection.rollback(sp);
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        }finally {
            try {
                connection.commit();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            jdbcUtils.close(connection,stmt,null);
        }
    }

批处理

public static  void test02(){
        JDBCUtils jdbcUtils = new JDBCUtils();
        //插入1000调记录
        Connection connection = null;
        PreparedStatement  pstmt = null;
        try {
            connection = jdbcUtils.getConnection();
            pstmt =   connection.prepareStatement("INSERT INTO cities VALUES(NULL,?,NULL)");
           long start = System.currentTimeMillis();
            for(int i=1;i<=10000;i++){
                pstmt.setString(1,"c"+i);
                pstmt.addBatch();
                if(i%1000==0){
                    pstmt.executeBatch();
                    pstmt.clearBatch();
                }
            }

            long end  = System.currentTimeMillis();
            System.out.println("===="+(end-start));
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            jdbcUtils.close(connection,pstmt,null);
        }
    }

获取自增主键的值

 public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        JDBCUtils jdbcUtils = new JDBCUtils();
        try {
            conn = jdbcUtils.getConnection();
            pstmt =  conn.prepareStatement("INSERT INTO cities VALUES(NULL,'c',NULL),(NULL,'c2',NULL);", Statement.RETURN_GENERATED_KEYS);

            pstmt.executeUpdate();
            rs =   pstmt.getGeneratedKeys();//为什么自增主键放到结果集中,因为一条sql语句可能插入多条记录
            while (rs.next()){
               Object id =  rs.getObject(1);
                System.out.println(id);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            jdbcUtils.close(conn,pstmt,rs);
        }
    }

callabledStatement的使用

 public  static  void test01(){
        Connection conn = null;
        CallableStatement cstmt = null;
        JDBCUtils jdbcUtils = new JDBCUtils();
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///mydb?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true","root","123456");
            cstmt = conn.prepareCall("{call demo08(?,?,?,?)}");
            cstmt.setInt(1,3);//输入类型的
            cstmt.registerOutParameter(2, Types.VARCHAR);//输出的类型
            cstmt.registerOutParameter(3,Types.VARCHAR);
            cstmt.registerOutParameter(4,Types.INTEGER);
            cstmt.execute();
            String name =   cstmt.getString(2);
            String subname =   cstmt.getString(3);
            int  score =   cstmt.getInt(4);
            System.out.println(name+"\t"+subname+"\t"+score);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jdbcUtils.close(conn,cstmt,null);
        }
    }
public static  void test02(){
        Connection conn = null;
        CallableStatement cstmt = null;
        JDBCUtils jdbcUtils = new JDBCUtils();
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///mydb?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true","root","123456");
            cstmt = conn.prepareCall("{?=call fun_02(?)}");//函数有返回值,第一个?接收饭盒的结果
            cstmt.registerOutParameter(1,Types.VARCHAR);
            cstmt.setInt(2,2);
            cstmt.execute();
            String res =   cstmt.getString(1);
            System.out.println(res);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jdbcUtils.close(conn,cstmt,null);
        }
    }

4、内容回顾

1>jdbc意义 接口 具体的实现是各个数据库厂商做的实现

2>jdbc使用步骤

添加Jar

加载驱动

获取链接

创建通道 发送sql指令

处理结果集

关闭资源

3>Statement sql注入

4>RestultSet next() getXXX()

5>PrepareStatement ? 占位符的方式

6>事务与批处理 主键自增 自动事务,可以设置手动 打点事务 pstmt批处理

7>CallabledStatement 调用存储过程和存储 函数的

5、面向对象的思想操作数据库

java 数据库【crud操作】

类 表

属性类型 列类型

属性属性名 列名

对象 记录

业务中也是crud操作

分层:单人单职

bean:实体类,与数据库表对应的,属性和数据库的字段对应

dao:数据访问层,与底层数据交互

view:与使用软件的人交互

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值