• java基础>jdbc数据库操作 小强斋


    一、JDBC简介及类型

    JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC为工具/数据库开发人员提供了一个标准的API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯 Java API 编写数据库应用程序。
    由于JDBC本身属于一个标准,所以一个数据库如果希望使用Java进行程序开发的话,那么各个数据库的生产商必须实现这些标准——提供专门的数据库的操作包。

    JDBC定义了4种不同的驱动程序,现分述如下:

    类型 1: JDBC-ODBC Bridge (JDBC-ODBC桥驱动程序)
    在JDBC出现的初期,JDBC-ODBC桥显然是非常有实用意义的,因为当时没有纯JDBC驱动。通过JDBC-ODBC桥,把jdbc方法翻译成ODBC函数调用,使Java应用程序可以通过访问ODBC驱动程序访问数据库。开发人员可以使用JDBC来存取ODBC数据源。不足的是,他需要在客户端安装ODBC驱动程序,换句话说,只能用于windows和Sun Solaris 操作系统。使用这一类型你需要牺牲JDBC的平台独立性。缺点是不易于移植,运行速度慢。

    2: JDBC-native driver bridge(本地库Java实现驱动程序)
    JDBC本地驱动程序桥提供了一种JDBC接口,它建立在已有本地数据库驱动程序的基础上。 将JDBC方法翻译成本地已有的专用驱动程序。其中的翻译工作采用Java语言实现,而专用驱动程序通常采用C语言编写,依赖于本地库文件运行,因此这种驱动程序中部分由Java实现。他的它的特点是能够利用已有的专用驱动程序,缺点是不具有跨平台型。
    JDBC驱动程序将对数据库的API从标准的JDBC调用转换为本地调用。使用此类型需要牺牲JDBC的平台独立性,还要求在客户端安装一些本地代码。


    类型 3: JDBC-network bridge(网络协议驱动程序)
    JDBC网络桥驱动程序不再需要客户端数据库驱动程序。它使用网络上的中间服务器来存取数据库。由中间件把JDBC方法翻译成数据库客户端请求,再向数据库服务器发送请求,中间件组件和数据库客户端通常位于中间层服务器上。此类驱动程序完全由Java实现,适用于基于网络的分布式应用。这种方式很灵活,但涉及网络安全问题。这种应用使得以下技术的实现有了可能,这些技术包括负载均衡、连接缓冲池和数据缓存等。具有平台独立性,而且不需要在客户端安装并取得控制权,所以很适合于Internet上的应用。

    类型 4: Pure Java driver(纯Java驱动方式)
    第4种类型是全新结构的驱动程序。它的特点是应用程序直接与数据库服务器端通信。这种方式需要数据库开发商的强力支持。提供基于特定数据库的网络插件,实现对特定数据库的通信协议,使JDBC驱动程序通过网络插件直接与数据库服务器通信。此类驱动程序全部采用Java编写。通过使用一个纯Java数据库驱动程序来执行数据库的直接访问。此类型实际上在客户端实现了2层结构。要在N-层结构中应用,一个更好的做法是编写一个EJB,让它包含存取代码并提供一个对客户端具有数据库独立性的服务。

               

                       ·类:DriverManager

                       ·接口:Connection、PreparedStatement、Statement、ResultSet

    二、主要接口简介

    2.1、DriverManager类创建与指定数据库连接

    public class DriverManager 
    
    {
    
      public static Connection  getConnection(String url, String user, String password)throws SQLException
    
      public static Connection  getConnection(String url) throws SQLException 
    
    }
    

    2.2、Connection接口管理连接对象

    public interface Connection 
    
    {
    
        Statement  createStatement() throws SQLException;                      //创建执行SQL的语句对象
    
        Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException;
    
                                                      //参数指定结果集属性
    
        void close() throws SQLException;             //关闭数据库连接
    
        boolean isClosed() throwsSQLException;                            //判断数据库连接是否已关闭
    
        DatabaseMetaData getMetaData() throwsSQLException;                   //获取所连接数据库的元数据
    
    }
    

    2.3、DatabaseMetaData接口获得数据库元数据

    public interface DatabaseMetaData 
    
    {
    
        String   getURL() throws SQLException;              //返回连接数据库的URL
    
        String getUserName()throws SQLException;    //返回数据库的用户名
    
        String getDatabaseProductName() throwsSQLException;                          //返回数据库名称
    
        String getDatabaseProductVersion()throws SQLException;                          //返回数据库版本号
    
        String getDriverName() throwsSQLException;    //返回驱动程序名称
    
        String getDriverVersion() throwsSQLException;  //返回驱动程序版本号
    
    }
    

    2.4、Statement接口执行SQL语句

    public interface Statement 
    
    {
    
        int executeUpdate(String sql) throwsSQLException;       //执行数据定义和数据更新SQL语句
    
        ResultSet executeQuery(String sql) throws SQLException;     //执行数据查询SQL语句
    
        boolean execute(String sql) throwsSQLException;         //执行SQL语句
    
        int getUpdateCount() throwsSQLException;                 //获得数据更新所影响的行数
    
        ResultSet getResultSet() throwsSQLException;            //获得数据查询结果集
    
        void close() throws SQLException;       //关闭语句
    
    }
    

    2.5、ResultSet接口存储结果集

    int getRow() throws SQLException;           //获得当前行位置
    
    boolean next() throws SQLException;                             //设置当前行的后一行成为新的当前行
    
     //获得当前行指定列的数据项值
    
    Object getObject(int columnIndex) throws SQLException;
    
    Object getObject(String columnName) throws SQLException;
    
    String getString(int columnIndex) throws SQLException;
    
    String getString(String columnName) throws SQLException;
    

    例如,

    while(resultset.next())
    
    System.out.println(resultset.getString(1));       //获得当前行指定列的值
    

    2.6、ResultSetMetaData接口从结果集中获得元数据

    public interface ResultSetMetaData 
    
    {
    
        int getColumnCount()throws SQLException;     //返回列数
    
        StringgetColumnName(int column) throws SQLException;                  //返回列名
    
        StringgetColumnTypeName(int column) throws SQLException;   //返回列数据类型名
    
        intgetColumnDisplaySize(int column) throws SQLException;              //返回列所占的最大字符宽度
    
    }
    

    三、数据库操作例子

    3.1、获得数据库连接

    在进行数据库连接的时候需要使用以下的几个信息:

                       ·数据库的驱动程序:oracle.jdbc.driver.OracleDriver

                       ·连接地址:jdbc:oracle:thin:@localhost:1521:orcl

                       ·用户名:scott

                       ·密码:tiger

    要想连接需要使用Connection接口进行连接对象的保存,但是此接口必须依靠DriverManager类才可以完成对象的实例化操作。

    import java.sql.Connection;
    import java.sql.DriverManager;
    public class ConnectionDemo {
    	public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
    	public static final String MysqlDBDRIVER = "com.mysql.jdbc.Driver";//mysql
    	public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl";
            public static final String MysqlDBURL = "jdbc:mysql://localhost:3306/test";//mysql
    	public static final String DBUSER = "scott";
    	public static final String DBPASSWORD = "tiger";
    	public static void main(String[] args) throws Exception {
    		Connection conn = null; // 表示的是数据库连接
    		Class.forName(DBDRIVER); // 1、加载数据库驱动程序
    		conn = DriverManager.getConnection(DBURL, DBUSER, DBPASSWORD); // 连接数据库
    		System.out.println(conn); // 如果不为null,表示已连接
    		conn.close(); // 数据库的操作必须关闭
    	}
    }
    

     3.2、PreparedStatement接口实现增删改查

     在开发中不会使用Statement进行操作,而都使用其子接口PreparedStatement完成。

     PreparedStatement操作实际上属于预处理的操作。如果要创建PreparedStatement接口的对象需要依靠Connection接口中的prepareStatement()方法完成,而且必须传入一个预处理的SQL语句,所有的占位符使用“?”表示。

    如果现在执行的是模糊查询,要使用LIKE语句。

    建表:

    CREATE TABLE USERINFO
    
    ( ID       INTEGER NOT NULL,
    
     NAME     VARCHAR2(50),
    
     AGE      INTEGER,
    
     BIRTHDAY DATE)
    

    增删改查语句:

    INSERT INTO 表名称(列名称1,列名称2,…) VALUES (值1,值2,…) ;

    UPDATE 表名称 SET 字段=值,字段=值,.. [WHERE更新条件]

    DELETE FROM 表名称 [WHERE删除条件]

     数据库的更新操作本身非常的容易,直接使用executeUpdate()语句,但是如果要是查询的话就不一样,查询使用的方法是executeQuery()方法完成

    方法:public ResultSet executeQuery(String sql) throwsSQLException

    查询的时候是将所有的内容都保存在了ResultSet接口的对象之中。取得ResultSet对象之后,就可以通过next()方法往下取每一行的数据,但是需要注意的是,如果要想取出某一列的内容,则使用getXxx()的形式,其中Xxx表示的是具体的数据类型,例如:getFloat()、getInt()、getDate()。既可以根据列名称,也可以根据列编号,从1开始

    package com;
    
    import java.sql.Connection;
    
    import java.sql.DriverManager;
    
    import java.sql.PreparedStatement;
    
    import java.sql.ResultSet;
    
    import java.util.Date;
    
    public class Insert {
    
     public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
    
     public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl";
    
     public static final String DBUSER = "wangshengzhuang";
    
     public static final String DBPASSWORD = "wangshengzhuang";
    
     public static void main(String[] args) throws Exception {
    
      Connection conn = null;
    
      Class.forName(DBDRIVER);
    
      conn = DriverManager.getConnection(DBURL, DBUSER, DBPASSWORD);
    
      // 插入数据
    
      String insertSql = "insert  into userinfo(id,name,age,birthday) values(?,?,?,?)";
    
      PreparedStatement pstmt = conn.prepareStatement(insertSql);
    
      pstmt.setInt(1, 1);
    
      pstmt.setString(2, "wangshengzhuang");
    
      pstmt.setInt(3, 23);
    
      pstmt.setDate(4, new java.sql.Date(new Date().getTime()));
    
      Integer len = pstmt.executeUpdate();
    
      System.out.println("插入" + len + "行数据");
    
      // 修改数据
    
      String updateSql = "update  userinfo set age=24 where id=?";
    
      pstmt = conn.prepareStatement(updateSql);
    
      pstmt.setInt(1, 1);
    
      len = pstmt.executeUpdate();
    
      System.out.println("修改" + len + "行数据");
    
      // 查询数据
    
      String querySql = "select* from userinfo where id=?";
    
      pstmt = conn.prepareStatement(querySql);
    
      pstmt.setInt(1, 1);
    
      ResultSet rs = pstmt.executeQuery();
    
      while (rs.next()) {
    
       Integer id = rs.getInt(1);
    
       String name = rs.getString(2);
    
       Integer age = rs.getInt(3);
    
       Date date = rs.getDate(4);
    
       System.out.println("id-->" + id + "name-->" + name + "age-->" + age
    
       + "birthday-->" + date);
    
      }
    
      // 删除数据
    
      String deleteSql = "delete from userinfo where id=?";
    
      pstmt = conn.prepareStatement(deleteSql);
    
      pstmt.setInt(1, 1);
    
      len = pstmt.executeUpdate();
    
      System.out.println("删除" + len + "行数据");
    
      rs.close();
    
      pstmt.close();
    
      conn.close(); // 数据库的操作必须关闭
    
     }
    
    }
    

    3.3、批处理

    在JDBC 2.0之后增加了许多的新功能,例如:可滚动的结集、使用ResultSet更新数据库、批处理等等,所谓的批处理就是指所有的操作可以一次性的提交到数据库之中。

    如果要使用批处理则需要使用Statement接口中的addBatch()方法。

    package com;
    
     
    
    import java.sql.Connection;
    
    import java.sql.DriverManager;
    
    import java.sql.PreparedStatement;
    
    import java.util.Date;
    
     
    
    publicclass Batch {
    
        publicstaticfinal String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
    
        publicstaticfinal String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl";
    
        publicstaticfinal String DBUSER = "wangshengzhuang";
    
        publicstaticfinal String DBPASSWORD = "wangshengzhuang";
    
     
    
        publicstaticvoid main(String[] args) throws Exception {
    
           Connection conn = null;
    
           Class.forName(DBDRIVER);
    
           conn = DriverManager.getConnection(DBURL, DBUSER, DBPASSWORD);
    
           // 插入数据
    
           String insertSql = "insert into userinfo(id,name,age,birthday) values(?,?,?,?)";
    
           PreparedStatement pstmt = conn.prepareStatement(insertSql);
    
     
    
           pstmt.setInt(1, 1);
    
           pstmt.setString(2, "wangshengzhuang");
    
           pstmt.setInt(3, 23);
    
           pstmt.setDate(4, new java.sql.Date(new Date().getTime()));
    
           pstmt.addBatch();
    
     
    
           pstmt.setInt(1, 2);
    
           pstmt.setString(2, "wangshengqi");
    
           pstmt.setInt(3, 24);
    
           pstmt.setDate(4, new java.sql.Date(new Date().getTime()));
    
           pstmt.addBatch();
    
     
    
           int score[] = pstmt.executeBatch();
    
           for (int i = 0; i < score.length; i++) {
    
               System.out.println(score[i]);
    
           }
    
     
    
           pstmt.close();
    
           conn.close(); // 数据库的操作必须关闭
    
     
    
        }
    
     
    
    }
    

    此时,一次性的会将所有的SQL语句发送到数据库之中执行,一次性更新5条记录。那么如果现在假设这5条记录都是有关联的5条。在使用批处理的操作中发现,如果中间有一条语句出错了,则默认情况下是将出错之前的代码进行提交,这是由于JDBC采用了自动的事务提交的方式才造成的结果。

    3.4、事务处理

     如果此时要进行事务处理的话,则需要按照如下的方式进行:

              1  取消自动提交:public void setAutoCommit(boolean autoCommit) throws SQLException

              2  执行更新操作:

              3  如果没有错误,则提交事务:public void commit() throwsSQLException

              4  如果有错误,则进行回滚:public void rollback() throwsSQLException

    package com;
    
     
    
    import java.sql.Connection;
    
    import java.sql.DriverManager;
    
    import java.sql.PreparedStatement;
    
    import java.util.Date;
    
     
    
    publicclass Transaction {
    
     
    
        publicstaticfinal String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
    
        publicstaticfinal String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl";
    
        publicstaticfinal String DBUSER = "wangshengzhuang";
    
        publicstaticfinal String DBPASSWORD = "wangshengzhuang";
    
     
    
        publicstaticvoid main(String[] args) throws Exception {
    
           Connection conn = null;
    
           Class.forName(DBDRIVER);
    
           conn = DriverManager.getConnection(DBURL, DBUSER, DBPASSWORD);
    
           conn.setAutoCommit(false);
    
           // 插入数据
    
     
    
           String insertSql = "insertinto userinfo(id,name,age,birthday) values(?,?,?,?)";
    
           PreparedStatement pstmt = conn.prepareStatement(insertSql);
    
        
    
               pstmt.setInt(1, 1);
    
               pstmt.setString(2, "wangshengzhuang");
    
               pstmt.setInt(3, 23);
    
               pstmt.setDate(4, new java.sql.Date(new Date().getTime()));
    
               pstmt.executeUpdate();
    
     
    
               pstmt.setInt(1, 1);
    
               pstmt.setString(2, "wangshengqi");
    
               pstmt.setInt(3, 24);
    
               pstmt.setDate(4, new java.sql.Date(new Date().getTime()));
    
               try{
    
               pstmt.executeUpdate();
    
               conn.commit();
    
     
    
           }catch (Exception e) {
    
               System.out.println("回滚");
    
               conn.rollback();
    
           }
    
     
    
           pstmt.close();
    
           conn.close(); // 数据库的操作必须关闭
    
     
    
        }
    
     
    
    }
    

    四、ResultSet进一步讨论

    ResultSet常用方法  JDBC 2.0 API  为结果集增加了两个新的基本能力:可滚动性和可更新性。 

    Statement createStatement(int resultSetType,int resultSetConcurrency) throws SQLException

    创建一个Statement对象,该对象将生成具有给定类型和并发性的ResultSet对象。此方法与上createStatement方法相同,但它允许重写默认结果集类型和并发性。

    参数:resultSetType -结果集类型,表明结果集是否可以滚动,它是ResultSet.TYPE_FORWARD_ONLYResultSet.TYPE_SCROLL_INSENSITIVEResultSet.TYPE_SCROLL_SENSITIVE之一。

    ResultSet.TYPE_FORWARD_ONLY:(缺省类型),ResultSet指针只允许向前移动,并且不会受到其他用户对该数据库所作更改的影响。

    TYPE_SCROLL_INSENSITIVE:ResultSet指针可以前后移动,甚至可以进行特定定位,例如移至列表中的第四个记录或者从当前位置向后移动两个记录。不会受到其他用户对该数据库所作更改的影响。
    TYPE_SCROLL_SENSITIVE:ResultSet指针可以前后移动,也可以定位,但这种类型受到其他用户所作更改的影响。

    resultSetConcurrency -并发类型;该参数确定是否可以更新 ResultSet它是ResultSet.CONCUR_READ_ONLYResultSet.CONCUR_UPDATABLE之一。

    CONCUR_READ_ONLY:这是缺省值,当前ResultSet对象只能读,不能更新。
    CONCUR_UPDATABLE:当前ResultSet可以更新

    返回:一个新的Statement对象,该对象将生成具有给定类型和并发性的ResultSet对象

    抛出:SQLException - 如果发生数据库访问错误,或者给定参数不是指示类型和并发性的ResultSet常量


    在滚动结果集中可用的方法有:        

    rs.previous();//向前滚动        

    rs.next();//向后滚动        

    rs.getRow();//得到当前行号        

    rs.absolute(n);//光标定位到n行        

    rs.relative(int n);//相对移动n行        

    rs.first();//将光标定位到结果集中第一行。        

    rs.last();//将光标定位到结果集中最后一行。        

    rs.beforeFirst()//将光标定位到结果集中第一行之前。        

    rs.afterLast();//将光标定位到结果集中最后一行之后。        

    rs.moveToInsertRow();//光标移到插入行        

    rs.moveToCurrentRow();//光标移回到调用

    rs.moveToInsertRow()方法前光标所在行        

    //测试光标位置        

    rs.isFirst()        

    rs.isLast()        

    rs.isBeforeFirst()        

    rs.isAfterLast()        

    在可更新结果集中可用的方法有:(单表)        

    rs.insertRow();//把插入行加入数据库和结果集        

    rs.deleteRow();//从数据库和结果集中删除当前行        

    rs.updateXXX(int column,XXX data);XXX代表int/double/String/Date中类型之一 

    rs.updateXXX(String columnName,String Data);    //以上两个方法更新结果集当前行        

    rs.updateRow();//更新内容发送到更新数据库

     

  • 相关阅读:
    关于document.onkeydown
    kubernetes PV存储卷类型 Marathon
    0015leetcode算法实现之三数之和3sumpython&golang实现 Marathon
    0018leetcode算法实现之四数之和4sumpython&golang实现 Marathon
    ubuntu20.04调整时区时间同步 Marathon
    0054leetcode算法实现之螺旋矩阵spiralMatrixpython&golang实现 Marathon
    0005剑指offer替换空格python&golang实现 Marathon
    使用 kubectl 管理 Secret Marathon
    0058leetcode算法实现之左翻转字符串reverseLeftStringpython%golang实现 Marathon
    0059leetcode算法实现之螺旋矩阵IIspiralMatrixIIpython&golang实现 Marathon
  • 原文地址:https://www.cnblogs.com/xiaoqiangzhaitai/p/5429395.html
Copyright © 2020-2023  润新知