zoukankan      html  css  js  c++  java
  • JavaWeb之JDBC

    一、介绍

    C#定义了ADO.Net接口来实现对SQLServer、Oracel等数据库的访问,那Java定义了JDBC接口实现对数据库的访问,数据库提供商只要实现这些接口,Java语言就能访问数据库。

    二、工作流程

    1、驱动引入

    数据库提供商实现了JDBC接口,可好几种数据库,Java知道是哪一种呢,于是乎得注册不同的驱动来操作对应的数据库,注册驱动也得要有驱动才是,所以首先是将驱动引入项目,这里用Mysql举例,之前也用C#操作过Mysql数据库,今天用Java操作,驱动下载地址:https://dev.mysql.com/downloads/file/?id=468319,将下载的文件解压,会找到mysql-connector-java-5.1.41-bin.jar文件,把该文件放入web-Info/lib下,这样就完成了驱动的引入。

    2、注册驱动

    引入驱动之后Java也不知道是用的什么数据库,所以得注册一下才知道是谁,注册之后会返回对应的驱动管理对象,就和入职一样,你到公司了但不报到那也不知道来了没来,报到了才会有针对个人的流程。

    3、创建连接

    数据库可能存放在远程,那怎么和数据库搭上呢,这就需要连接。

    4、执行操作

    连接上之后要干嘛呢,不能一直连着不干事情啊,所以连接之后执行数据库的操作,增删改查等。

    5、返回结果

    增删改查完了,总要有个回信吧,不然怎么知道成功与否,查询的话会返回查询的数据,增加、删除、修改会返回影响的行数。

    6、释放

    把结果也返回了,但不能老连着数据库啊,这样也占用资源,创建的对象也没释放,还占空间,所以用完了就把它关掉。

    上面大致把操作数据库的流程列了下,下面通过实验来操作一下。

    7、验证

    这里先在本地数据库创建一个数据库testdb,然后在表中创建一个users表,有id、name、age、birthday字段,代表着不同的数据类型。

    <%@page import="com.mysql.jdbc.Driver"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ page import="java.sql.*" %>
    <%@ page import="java.util.*"  %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <%
    
        Connection conn=null;
        Statement stmt=null;
        ResultSet rs=null;
        try{   
        //注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        //通过注册的驱动获得连接对象Connection
        conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb","root","123456");
        //通过Statement对象执行操作 返回结果ResultSet
        stmt=conn.createStatement();
        //返回结果 
        rs=stmt.executeQuery("select * from users");
        
        while(rs.next())
        {
            out.println("姓名:"+rs.getString("name")+"  年龄:"+rs.getInt("age") +"  出生日期:"+rs.getDate("birthday"));
        }
    }
    catch(SQLException e)
    {
        out.println(e.getMessage());
        e.printStackTrace();
    }
    finally
    {
        //释放资源
        if(conn!=null)
        {
            conn.close();
        }
        if(stmt!=null)
        {
            stmt.close();
        }
        if(rs!=null)
        {
            rs.close();
        }
    }  
    %>
    </body>
    </html>
    View Code

    二、带参数的sql执行

    上面使用Statement来查询数据库,但是Statement不能使用带参数的sql,如果不带参数直接拼接sql语句则会有注入式攻击的风险,那如果要使用带参数的sql就需要用它的子类对象:PreparedStatement.用它可以防止注入式攻击。

    <%@page import="com.mysql.jdbc.Driver"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ page import="java.sql.*" %>
    <%@ page import="java.util.*"  %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <%
    
        Connection conn=null;
       
        ResultSet rs=null;
        PreparedStatement prestmt=null;
        try{   
        //注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        //通过注册的驱动获得连接对象Connection
        conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb","root","123456");
        String sql="insert into users (name,age,birthday) values(?,?,?)";
        
        prestmt=conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
        prestmt.setString(1, "cuiyw");
        prestmt.setInt(2, 25);
        prestmt.setDate(3,new  java.sql.Date(new java.util.Date().getTime()));
        int result=prestmt.executeUpdate();
        
        if(result>0)
        {
            out.println("新增成功");
            rs=prestmt.getGeneratedKeys();
            while(rs.next())
            {
                out.println("生成的主键ID为:"+rs.getInt(1));
            }
        } 
    }
    catch(SQLException e)
    {
        out.println(e.getMessage());
        e.printStackTrace();
    }
    finally
    {
        //释放资源
        if(conn!=null)
        {
            conn.close();
        }
        if(prestmt!=null)
        {
            prestmt.close();
        }
        if(rs!=null)
        {
            rs.close();
        }
    }  
    %>
    </body>
    </html>
    View Code

    上面的代码实现了两个功能,一通过往users表中插入一条记录,使用PreparedStatement带参数的sql,二获取自动增长列的ID。ADO.Net中使用@@Identity,jdbc中使用getGeneratedKeys(),不过在实例化PreparedStatement的时候要带上Statement.RETURN_GENERATED_KEYS。

    三、批处理

    Statement、PreparedStatement能一次执行新增、修改、删除多条sql语句。一般批处理和事务一起使用,比如转账等。下面是事务批处理插入数据。

    <%@page import="com.mysql.jdbc.Driver"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ page import="java.sql.*" %>
    <%@ page import="java.util.*"  %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <%
    
        Connection conn=null;
       
        ResultSet rs=null;
        PreparedStatement prestmt=null;
        try{   
        //注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        //通过注册的驱动获得连接对象Connection
        conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb?rewriteBatchedStatements=true","root","123456");
        String sql="insert into users (name,age,birthday) values(?,?,?)";
        
        //开启事务
        conn.setAutoCommit(false);
        prestmt=conn.prepareStatement(sql);
        
        for(int i=0;i<2;i++)
        {
            
            prestmt.setString(1, "cuiyw"+i);
            prestmt.setInt(2, 25+i);
            prestmt.setDate(3,new  java.sql.Date(new java.util.Date().getTime()));
            prestmt.addBatch();
        }
        //批处理
        prestmt.executeBatch();
        //提交事务
        conn.commit();
        
        conn.setAutoCommit(true);
    
    }
    catch(SQLException e)
    {
        //回滚
        conn.rollback();
        out.println(e.getMessage());
        e.printStackTrace();
    }
    finally
    {
        //释放资源
        if(conn!=null)
        {
            conn.close();
        }
        if(prestmt!=null)
        {
            prestmt.close();
        }
        if(rs!=null)
        {
            rs.close();
        }
    }  
    %>
    </body>
    </html>
    View Code

    四、调用存储过程

     在使用数据库的过程中,可能会调用存储过程,可以使用CallableStatement来调用存储过程。

    调用存储函数 1.{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
    调用存储过程 2.{call <procedure-name>[(<arg1>,<arg2>, ...)]}

    通过CallableStatement对象的registerOutParameter() 方法注册Out参数

    通过CallableStatement对象的setXxx()方法设定IN或In out 参数,若想将参数设为null,可以使用setNUll()

    如果所调用的是带返回参数的存储过程还需要通过CallableStatement对象的getXxx()获取输出参数

    这里先创建了一个存储过程在数据库中,有一个输入参数一个输出参数

    <%@page import="com.mysql.jdbc.Driver"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ page import="java.sql.*" %>
    <%@ page import="java.util.*"  %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <%
    
        Connection conn=null;
       
        ResultSet rs=null;
        CallableStatement callstmt=null;
        try{   
        //注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        //通过注册的驱动获得连接对象Connection
        conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb?rewriteBatchedStatements=true","root","123456");
        callstmt=conn.prepareCall("{call selectUserById(?,?)}");
        callstmt.setInt(1, 2);
        callstmt.registerOutParameter(2, Types.INTEGER);
        rs=callstmt.executeQuery();
        while(rs.next())
        {
            out.println("姓名:"+rs.getString("name")+"  年龄:"+rs.getInt("age") +"  出生日期:"+rs.getDate("birthday"));
        }
        out.println("存储过程返回值:"+callstmt.getInt(2));
    }
    catch(SQLException e)
    {
        
        out.println(e.getMessage());
        e.printStackTrace();
    }
    finally
    {
        //释放资源
        if(conn!=null)
        {
            conn.close();
        }
        if(callstmt!=null)
        {
            callstmt.close();
        }
        if(rs!=null)
        {
            rs.close();
        }
    }  
    %>
    </body>
    </html>
    View Code

    五、其他

    对于jdbc操作二进制数据,比如图片,元数据、连接池就不一一介绍了,在开发中如果直接使用jdbc,这些也都会封装成一个类,现在的项目也一般使用框架来映射数据库才操作。

  • 相关阅读:
    八、基本数据结构(图形结构)
    七、基本数据结构(树形结构)
    4、使用 ImportTsv 将 Hive 数据导入 Hbase
    六、跳表
    五、二分法查找
    四、归并排序 && 快速排序
    一、kafka 介绍 && kafka-client
    三、排序之冒泡、插入、选择
    二、YARN
    三、synchronized & lock
  • 原文地址:https://www.cnblogs.com/5ishare/p/6596370.html
Copyright © 2011-2022 走看看