JAVA 高级特性 JDBC

 需要的jdbc jar 包:
数据持久化分为很多状态 
瞬时状态: 保存在内存的程序数据,程序退出后,数据就消失了,称为瞬时状态。
持久化:  将程序数据在瞬时状态和持久状态之间转换的机制。
持久状态: 保存在磁盘上的程序数据,程序退出后依然存在,称为程序数据的持久状态。

 数据持久化技术:

Hibernate : hibernate为应用程序提供了高效的O/R关系映射和查询服务,为面向对象的领域模型到传统的关系型数据库的映射,提供了一个使用方便的框架。
JPA :  JPA(Java Persistense API)是EJB3.0的一部分,为其提供了一套O/R关系映射的API,但不仅限于EJB中使用,它也可以在web应用或者应用程序客户端中被使用,
甚至在Java桌面程序中被使用。
JDBC :  JDBC API是一个Java API,可以访问任何类型的数据库的数据,尤其是存储在关系数据库中的数据。 
 JDBC 实现数据持久化。
 什么是JDBC ?
JDBC 代表Java数据库连接 (Java Database Connectivity)  ,它是用于Java编程语言和数据库之间的数据库无关连接的标准Java API ,换句话说 JDBC 是用于在Java 语言编程中与数据库连接的API 。
JDBC 库通常与数据库使用相关,如下面提到的每个任务的API 
1 , 连接到数据库。
2, 创建SQL语句
3,在数据库中执行SQL语句查询
4,查看和修改结果记录

常见JDBC组件。

DriverManager:     此类管理数据库驱动程序列表。 使用通信子协议将来自java应用程序的连接请求与适当的数据库驱动程序进行匹配。在JDBC下识别某个子协议的第一个驱动程序将用于建立数据库连接。
Driver:   此接口处理与数据库服务器的通信。我们很少会直接与Driver对象进行交互。 但会使用DriverManager对象来管理这种类型的对象。 它还提取与使用Driver对象相关的信息。
Connection:   此接口具有用于联系数据库的所有方法。 连接(Connection)对象表示通信上下文,即,与数据库的所有通信仅通过连接对象。
Statement:使用从此接口创建的对象将SQL语句提交到数据库。 除了执行存储过程之外,一些派生接口还接受参数。
ResultSet:在使用Statement对象执行SQL查询后,这些对象保存从数据库检索的数据。 它作为一个迭代器并可移动ResultSet对象查询的数据。
SQLException:此类处理数据库应用程序中发生的任何错误

数据库操作 : 

//加载驱动 
Class.forName( 驱动路径 ) 
//获取数据库连接
//jdbc:mysql://主机名 : 端口号 / 数据库名
DriverManager . getconnection
Statement 对象。
当获得了与数据库的连接,就可以与数据库进行交互了。JDBC Statement ,CallableStatement 和PreparedStatement  接口定义了可用于发送SQL 或PL/SQL命令。并从数据库接收数据的方法和属性,它们还定义了有助于在Java 和SQL数据类型的数据类型差异转换方法。
利用Statement 对象操作数据库。
 

PreparedStatement操作数据库   

Statement对数据库中的表内容进行增删改操作, 每次增加删除修改都需要加载数据库驱动,连接数据库,执行SQL语句,关闭数据库,这样的话,代码的重复量有些大,代码冗余比较明显,后来进行修改,运用了Java继承封装和多态的思想,对原来的增删改代码进行了优化,在现实的开发中常用PreparedStatement接口而不是Statement接口进行增删改操作:使用PreparedStatement对于代码的可维护性和可读性提高了;使用PreparedStatement尽最大可能提高性能;最重要的一点是极大地提高了安全性。
PreparedStatement是Statement接口的子接口,属于预处理操作,与直接使用Statement不同,PreparedStatement在操作时,是预先在数据表中准备好了一条SQL语句,但是此SQL语句的具体内容暂时不设置,而是之后在进行设置。
PreparedStatement实例包含已编译的SQL语句,SQL语句可能包含1个,2个或多个输入的值,这些值未被明确指定在SQL语句中用?作为占位符代替,之后执行SQL语句之前要用setXXX()方法对值进行写入。
PreparedStatement对象比Statement对象的执行速度要快,因为PreparedStatement对象已经预编译过了,因此需要多次执行的SQL语句也可以用PreparedStatement对象进行执行来加快执行速度。  作为Statement的子类,PreparedStatement接口继承了Statement的所有功能。另外它还整合一整套getXXX()和setXXX()方法,用于对值得获取和输入设置。同时,它还修改了三个方法execute、executeQuery、executeUpdate使它们不需要参数。这些方法的Statement形式,不应该再用于PreparedStatement对象。
常用方法摘要:

executeQuery:

用于产生单个结果集(ResultSet)的语句,例如:被执行最多的SELECT 语句。 
这个方法被用来执行 SELECT 语句,但也只能执行查询语句,执行后返回代表查询结果的ResultSet对象。
executeUpdate:
用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。
INSERT、UPDATE 或 DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数(int),指示受影响的行数(即更新计数)。对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。

execute: 

    可用于执行任何SQL语句,返回一个boolean值,表明执行该SQL语句是否返回了ResultSet。如果执行后第一个结果是ResultSet,则返回true,否则返回false。
但它执行SQL语句时比较麻烦,通常我们没有必要使用execute方法来执行SQL语句,而是使用executeQuery或executeUpdate更适合。但如果在不清楚SQL语句的类型时则只能使用execute方法来执行该SQL语句了。
  4:getMetaData():获取包含有关ResultSet对象列信息的ResultSetMetaData对象,ResultSet对象将在此执行PreparedStatement对象时返回。
  5:getParameterMetaData():获取此PreparedStatement对象的参数的编号、类型和属性。
  6:setAsciiStream(int parameterIndex, InputStream x, int longth):将指定参数设置为给定输入流,该输入流将具有给定字节数。
statement、PreparedStatement和CallableStatement区别和联系: 
1. Statement、PreparedStatement和CallableStatement都是接口(interface)。 
2. Statement继承自Wrapper、PreparedStatement继承自Statement、CallableStatement继承自PreparedStatement。 
3. Statement接口提供了执行语句和获取结果的基本方法; 
    PreparedStatement接口添加了处理 IN 参数的方法; 
    CallableStatement接口添加了处理 OUT 参数的方法。 
4. a. Statement: 
    普通的不带参的查询SQL;支持批量更新,批量删除; 
 
     b. PreparedStatement: 
     可变参数的SQL,编译一次,执行多次,效率高; 
     安全性好,有效防止Sql注入等问题; 
     支持批量更新,批量删除; 
     c. CallableStatement: 
  继承自PreparedStatement,支持带参数的SQL操作; 
  支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持; 
Statement每次执行sql语句,数据库都要执行sql语句的编译 ,最好用于仅执行一次查询并返回结果的情形时,效率高于PreparedStatement。
PreparedStatement是预编译的,使用PreparedStatement有几个好处 
1. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。 
2. 安全性好,有效防止Sql注入等问题。 
3.  对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch; 
4.  代码的可读性和可维护性。 
 
注: 
executeQuery:返回结果集(ResultSet),预编译状态下executeQuery( ) 不能传入参数,只有statement 连接对象才能传入参数
executeUpdate: 执行给定SQL语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句, 
或者不返回任何内容的SQL语句(如 SQL DDL 语句)。 
execute: 可用于执行任何SQL语句,返回一个boolean值, 
表明执行该SQL语句是否返回了ResultSet。如果执行后第一个结果是ResultSet,则返回true,否则返回false。 
 
假设现在有一个本地数据库 localhost 利用java 代码 进行数据库操作;
package com.project.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import java.sql.CallableStatement;
public class JdbcDemo {
    private static final String url = "jdbc:mysql://localhost:3306/test";
    private static final String userName = "root";
    private static final String passWord = "";
    //初始化驱动,静态代码块
    static {
        try {
            // 加载驱动
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }   
    public static void main(String[] args) {
        JdbcDemo demo = new JdbcDemo();
        // 创建一个 Connection 连接对象 通过一个连接对象操作数据库,一个连接多个操作
        Connection con = JdbcDemo.getcon();
        //demo.updateprepareDemo(con);
        demo.callableDemo(con);
        demo.selectDemo(con);
        JdbcDemo.closeDemo(con);
    }
          //调用存储过程
     public void callableDemo(Connection con){
         //准备SQL
         String SQL ="{CALL test(?,?,?,?)}";
         //创建连接状态
         try {
            CallableStatement state = con.prepareCall(SQL);
            //设置参数
            state.setString(1, "LIDAHU");
            state.setInt(2, 23);
            state.setString(3, "man");
            state.registerOutParameter(4, java.sql.Types.INTEGER);
            //执行SQL
            state.execute();
            //处理结果
            //获取参数
            int result = state.getInt(4);
            if (result==1){
                System.out.println("注册成功!");
            }else {
                System.out.println("注册失败!");
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
     }
        //利用预编译preparedstatement进行更新操作
    public void updateprepareDemo(Connection con) {
        // 准备SQL语句
//      String SQL1 = "INSERT INTO student(id,name,age,sex) VALUES(8,'YANGWU',18,'woman')";
//      String SQL2 = "DELETE FROM student WHERE id=1";  
        // 提交数据库的对象
        PreparedStatement state = null;
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入修改的姓名 :");
        String name = sc.nextLine();
        System.out.println("请输入年龄 : ");
        int age = sc.nextInt();
        //关闭自动提交 , 事务不会实现数据持久化,即不会写入到数据库里面
        try {
            con.setAutoCommit(false);
        } catch (SQLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        String SQL3 = "UPDATE student SET name=? WHERE age=?";
        System.out.println(SQL3);
        //获取状态
        try {
            state = con.prepareStatement(SQL3);
            //设置参数, SQL语句里面的 ? 按照顺序。
            state.setString(1, name);       
            state.setInt(2,age);
            //executeUpdate 返回一个执行影响行数的int 提交SQL语句,执行SQL
            int set = state.executeUpdate();
            //处理执行结果
            if (set > 0) {
                //结束事务 , 数据上传到数据库, 实现持久化
con.commit();
                System.out.println("执行成功: " + set + "行");
            }else {
                //让其回滚。
                con.rollback();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                state.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //更新SQL 操作
    @SuppressWarnings("unused")
    public void updateDemo(Connection con) {
        // 准备SQL语句
        String SQL1 = "INSERT INTO student(id,name,age,sex) VALUES(8,'YANGWU',18,'woman')";
        String SQL2 = "DELETE FROM student WHERE id=1";
        String SQL3 = "UPDATE student SET name='NIHAO' WHERE id = 1";
        // 提交数据库的对象
        Statement state = null;
        try {
            state = con.createStatement();
            //executeUpdate 返回一个执行行数的int
            int set = state.executeUpdate(SQL1);
            System.out.println(set);
            if (set > 0) {
                System.out.println("执行成功: " + set + "行");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                state.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //获取连接对象
    public static Connection getcon(){
        Connection con = null;
        try {
            // 获取数据库连接
            con = DriverManager.getConnection(url, userName, passWord);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return con;
    }
        
    
    // 查询方法
    public void selectDemo(Connection con) {
        // 步骤:
        // 创建提交对象,,结果集对象
        Statement state = null;
        ResultSet set = null;
        // 准备SQL语句
        String sql = "select * from student";
        // 执行SQL语句
        // 创建提交数据库的连接
        try {
            // 连接对象 ,执行executeQuery查询命令,并保存到结果集set里面
            state = con.createStatement();
            set = state.executeQuery(sql);
            // 处理结果集(对set 结果集进行遍历操作)
            // next(); 切换到下一条目标数据,如果存在下一条数据则返回true ,否则返回false
            while (set.next()) {
                // 每次循环操作一条结果
                int id = set.getInt("id");
                String name = set.getString("name");
                String sex = set.getString("sex");
                int age = set.getInt("age");
                System.out.println(id + " " + name + " " + sex + " " + age+ ";");
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                state.close();
                set.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }       
    }
    public static void closeDemo(Connection con) {
        // 关闭数据库连接
        // 处理异常
        try {
            con.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
 
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/thelovelybugfly/p/10821962.html