java基础(十三):JDBC

目录

  • JDBC概述
  • 使用JDBC完成添加/更新/删除操作
  • 使用JDBC完成查询操作
  • JDBC语法总结
  • 使用PreparedSatement完善JDBC操作
  • 手动启动事务管理
  • 使用JDBC完成多表查询操作
  • 采用分层实现JDBC操作

JDBC概述

JDBC(Java Data Base Connectivity,Java数据库连接)

是一种用于执行SQL语句的Java API,为多种关系数据库提供统一访问

它由一组用Java语言编写的类和接口组成

程序员只需用JDBC API写一个程序,就可以访问所有数据库。

JDBC API

  提供者:Sun公司

  内容:供程序员调用的接口与类,集成在java.sql和javax.sql包中,如

        DriverManager类  作用:管理各种不同的JDBC驱动

        Connection接口

        Statement接口

        ResultSet接口

JDBC 驱动

  提供者:数据库厂商

  作用:负责连接各种不同的数据库

JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型。

三方关系

  SUN公司是规范制定者,制定了规范JDBC(连接数据库规范)

  数据库厂商微软、甲骨文等分别提供实现JDBC接口的驱动jar包

  程序员学习JDBC规范来应用这些jar包里的类。

简单地说,JDBC 可做三件事:

  与数据库建立连接、发送 操作数据库的语句并处理结果。

  • DriverManager :依据数据库的不同,管理JDBC驱动
  • Connection :负责连接数据库并担任传送数据的任务
  • Statement :由 Connection 产生、负责发送执行SQL语句
  • ResultSet:负责保存Statement执行后所产生的查询结果

JDBC语法总结

  • 1:加载一个Driver驱动
  • 2:创建数据库连接(Connection)
  • 3 :创建SQL命令发送器Statement
  • 4:通过Statement发送SQL命令并得到结果
  • 5:处理SQL结果(select语句)
  • 6:关闭数据库资源
    • ResultSet
    • Statement
    • Connection。

1.加载驱动

加载JDBC驱动是通过调用方法java.lang.Class.forName(),

下面列出常用的几种数据库驱动程序加载语句的形式 :

  • Class.forName(“oracle.JDBC.driver.OracleDriver”);//使用Oracle的JDBC驱动程序
  • Class.forName(“com.microsoft.JDBC.sqlserver.SQLServerDriver”);//使用SQL Server的JDBC驱动程序
  • Class.forName(“com.ibm.db2.JDBC.app.DB2Driver”);//使用DB2的JDBC驱动程序
  • Class.forName("com.mysql.JDBC.Driver");//使用MySql的JDBC驱动程序

2.创建数据库连接

与数据库建立连接的方法是调用

DriverManager.getConnection(String url, String user, String password )方法

  • Connection conn=null;
  • String url="jdbc:oracle:thin:@localhost:1521:orcl";
  • String user=“scott";
  • String password=“tiger";
  • conn = DriverManager.getConnection(url, user, password);

3.创建Statement并发送命令

  • Statement对象用于将 SQL 语句发送到数据库中,或者理解为执行sql语句
  • 有三种 Statement对象:
    • Statement:用于执行不带参数的简单SQL语句;
    • PreparedStatement(从 Statement 继承):用于执行带参数或不带参数的预编译SQL语句;
    • CallableStatement(从PreparedStatement 继承):用于执行数据库存储过程的调用。

4.处理ResultSet结果

  • ResultSet对象是executeQuery()方法的返回值,它被称为结果集,它代表符合SQL语句条件的所有行,并且它通过一套getXXX方法(这些get方法可以访问当前行中的不同列)提供了对这些行中数据的访问
  • ResultSet里的数据一行一行排列,每行有多个字段,且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSet的next()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环
  • ResultSet对象自动维护指向当前数据行的游标每调用一次next()方法,游标向下移动一行
  • 初始状态下记录指针指向第一条记录的前面,通过next()方法指向第一条记录。循环完毕后指向最后一条记录的后面。

5.关闭数据库资源

  (1)作为一种好的编程风格,应在不需要Statement对象和Connection对象时显式地关闭它们

      关闭Statement对象和Connection对象的语法形式为:

        public void close() throws SQLException

  (2)用户不必关闭ResultSet。当它的 Statement 关闭、重新执行或用于从多结果序列中获取下一个结果时,该ResultSet将被自动关闭。

注意:要按先ResultSet结果集,后Statement,最后Connection的顺序关闭资源,因为Statement和ResultSet是需要连接是才可以使用的,所以在使用结束之后有可能其他的Statement还需要连接,所以不能先关闭Connection。

  • PreparedStatement 接口继承 Statement接口
  • PreparedStatement比普通的Statement对象使用起来更加灵活,更有效率

 代码示例

demo1

package cn.sxt.jdbc.demo1;

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;

public class Tester {

    /**
     * 引入驱动Jar
     *         JRE System Library——>鼠标右键——>build Path——>Config build Path ——〉Libraries——〉add external jars
     * 访问数据库的步骤
     *         1、加载驱动
     *         2、创建数据库连接
     *         3、创建语句发送器Statement
     *         4、Statement对象发送Sql语句(发送给服务器)
     *         5、处理服务器的响应结果
     *         6、关闭资源
     * 
     * connection
     *         一个数据库连接对象
     * Statement
     *         概述
     *             将Sql语句发送给数据库服器(也可以理解为Sql语句的执行者)
     *         对象    
     *             Statement            :可以执行不带参数的Sql语句
     *             PreparedStatement    :执行执行带参数和不带参数的Sql语句
     *             CallableStatement    :用于执行存储过程的Satatement
     * 
     *             PreparedStatement比Statement更加方便灵活。所以一般使用PreparedStatement
     *         方法
     *             executeUpdate()        :执行非查询语句(insert、delete、update)
     *             executeQuery()        :执行查询语句(select)
     * @param args
     * @throws ClassNotFoundException 
     * @throws SQLException 
     */
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Scanner input = new Scanner(System.in);
        
        //6、结果处理
        /*
        if(delete(50) >0)
            System.out.println("数据删除成功");
        else
            System.out.println("数据删除失败");
            
        int count = add(70, "tdt","nj");
        System.out.println(count);
        
        getAll();
        */
        
        System.out.print("请输入部门ID:");
        int id = input.nextInt();
        
        System.out.println("请输入部门名称:");
        String name = input.next();
        
        System.out.println("请输入部门所在地:");
        String loc = input.next();
        
        System.out.println(add(id, name, loc));
        
        
    }
    
    static String url = "jdbc:oracle:thin:@localhost:1521:oracle";
    static String user = "scott";
    static String password = "tiger";
    
    /**
     * 查询所有数据
     */
    static void getAll(){
        
        try {
            //1、加载驱动
            Class.forName("oracle.jdbc.driver.OracleDriver");
            
            //2、获取连接对象
            Connection conn = DriverManager.getConnection(url,user, password);
            
            //3、创建statement对象
            Statement statement = conn.createStatement();
                        
            //4、执行语句
            String sql = "select * from dept";
            ResultSet rs = statement.executeQuery(sql);
            //5、处理查询结果
            while(rs.next()){
                System.out.println(rs.getInt("DeptNo") + "	" + rs.getString("DName") + "	" +rs.getString("Loc"));
            }
            //6、关闭资源
            rs.close();
            statement.close();
            conn.close();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
    /**
     * 将部门信息添加到dept表中
     * @param id
     * @param name
     * @param loc
     * @return
     */
    static int add(int id, String name, String loc){    
        int count = 0;
        try {
            //1、加载驱动
            Class.forName("oracle.jdbc.driver.OracleDriver");
            
            //2、获取连接对象
            Connection conn = DriverManager.getConnection(url, user, password);
            
            //3、创建statement对象
            Statement statement = conn.createStatement();
            
            //4、执行Sql语句
            //拼接Sql语句
            String sql = "insert into dept values(" + id +",'" +name+ "','"+loc+"')";
            System.out.println(sql);
            count =  statement.executeUpdate(sql);
            
            //5、关闭对象
            statement.close();
            conn.close();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return count;
    }
    
    /**
     * 使用Statement执行非查询语句
     * @param id
     * @return
     */
    static int delete2(int id){
        int count = 0;
        
        try {
            //1、加载驱动
            Class.forName("oracle.jdbc.driver.OracleDriver");
            
            //2、获取连接对象
            Connection conn =  DriverManager.getConnection(url, user, password);
            
            //3、创建Statement对象
            Statement statement = conn.createStatement();
            
            //4、执行命令
            String sql = "delete from dept where deptNo=" + id;
            count = statement.executeUpdate(sql);
            
            //5、关闭资源
            statement.close();
            conn.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return count;
    }
    
    /**
     * 按照ID删除部门信息
     *         使用preparedStatement对象进行实现
     * @param id
     */
    static int delete(int id){
        int count = 0;
        
        try {
            // 1、加载JDBC驱动
            Class.forName("oracle.jdbc.driver.OracleDriver");
            
            // 2、创建数据库连接
            // jdbc:oracle:thin :固定的,前缀,表示当前连接数据库的类型信息
            // localhost :本地服务器的地址
            // 1521 :数据库服务器的端口
            // oracle :数据库实例的名称
            //String url = "jdbc:oracle:thin:@localhost:1521:oracle";
            //String user = "scott";
            //String password = "tiger";
            // DriverManager :驱动管理器
            // getConnection() :根据驱动信息可以获取到一个连接对象——Connection
            Connection conn = DriverManager.getConnection(url, user, password);

            // 3、获取Statement对象
            String sql = "delete from dept where deptNo =" + id;
            PreparedStatement statement = conn.prepareStatement(sql);

            // 4、发送Sql语句(执行Sql语句)
            // executeUpdate() :将Sql语句发送给数据库服器(返回值:执行该语句后受影响的行数)
            count = statement.executeUpdate();
            
            // 5、关闭资源
            statement.close();
            conn.close();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return count;
    }

}

demo2

package cn.sxt.jdbc.demo2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

/**
 * "insert into dept values(" + id +",'" +name+ "','"+loc+"')"
 * Sql语句的生成方式是拼接Sql语句
 * 拼接Sql语句容易造成Sql注入攻击。注入攻击可能造成系统崩溃
 * 
 * 命令行参数
 *         意义
 *             1、有效的避免注入攻击,更加安全可靠
 * 
 *         实现
 *             PreparedStatement对象
 *                 方法
 *                     setXxxx(参数索引,值)
 *                 说明
 *                     setXxxx        :设置指定类型的参数给PreparedStatement对象
 *                     参数索引        :当前设置的参数的索引位置,从1开始
 *                     值            :需要设置的参数之
 * @author Terry
 *
 */
public class Tester {
    static String url = "jdbc:oracle:thin:@localhost:1521:oracle";
    static String user = "scott";
    static String password = "tiger";

    /**
     * @param args
     */
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        
        System.out.print("请输入部门ID:");
        int id = input.nextInt();
        
        System.out.print("请输入部门名称:");
        String name = input.next();
        
        System.out.print("请输入部门所在地:");
        String loc = input.next();
        
        int c = add(id, name, loc);
        System.out.println(c);
    }
    
    /**
     * 使用参数化的方式执行非查询语句
     * @param id
     * @param name
     * @param addr
     * @return
     */
    static int add(int id, String name ,String addr){    
        int count = 0;
        try {
            //1、加载驱动
            //通过反射加载对应的类
            Class.forName("oracle.jdbc.driver.OracleDriver");
            
            //2、获取连接对象            
            Connection con = DriverManager.getConnection(url, user, password);
            
            //3、创建Statement对象
            //?表示语句执行过程中所需要的参数
            String sql = "insert into dept values(?,?,?)";
            //带有参数的语句需要通过PreparedStatement对象才能执行
            PreparedStatement statement= con.prepareStatement(sql);
            
            //将参数传递给Statement对象
            //将int类型参数——id传递给Statement对象
            statement.setInt(1,id);
            statement.setString(2, name);
            statement.setString(3, addr);
            
            //4、执行Sql语句
            count = statement.executeUpdate();
            
            //5、关闭资源
            statement.close();
            con.close();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return count;
    }

}

demo3

工具类:可以实现执行查询语句和非查询语句

package cn.sxt.util;

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

/**
 * 工具类
 *         可以实现执行查询语句和非查询语句
 * @author Terry
 *
 */
public class DBUtil {
    //数据库连接参数
    private static String url = "jdbc:oracle:thin:@localhost:1521:oracle";
    private static String user = "scott";
    private static String password = "tiger";
    
    //定义JDBC对象
    Connection con = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    
    /**
     * 加载驱动并初始化Connection对象
     */
    private void init(){        
        try {
            //加载驱动
            Class.forName("oracle.jdbc.driver.OracleDriver");
            
            //获取连接对象
            con = DriverManager.getConnection(url, user, password);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
    /**
     * 执行非查询语句
     * eg:insert、delete及update
     * @param sql
     * @return        :受影响行数
     */
    public int executeUpdate(String sql,Object...parameters){
        //初始化Connection对象
        init();
                
        try {
            //获取Prepared对象
            ps = con.prepareStatement(sql);
            
            //为PreparedStatement初始化参数
            for(int i = 1;i<=parameters.length;i++){
                //i-1    :因为数组的下标是从0开始的。所以这里需要使用i-1
                ps.setObject(i, parameters[i-1]);
            }
            
            //执行Sql语句
            return ps.executeUpdate();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally{
            close();
        }
        
        return -1;
    }
    
    /**
     * 执行查询语句
     * 注意:ResultSet(连接式的数据访问对象)使用过程中JDBC不能关闭
     * @param sql
     * @return        :查询结果集
     */
    public ResultSet executeQuery(String sql,Object...parameters){
        //初始化Connection对象
        init();
                
        try {
            //获取PreparedStatement对象
            ps = con.prepareStatement(sql);
            
            //为PreparedStatement初始化参数
            for(int i = 1;i<=parameters.length;i++){
                //i-1    :因为数组的下标是从0开始的。所以这里需要使用i-1
                ps.setObject(i, parameters[i-1]);
            }
            
            //执行语句
            return ps.executeQuery();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }        
        return null;
    }
    
    /**
     * 关闭所有的JDBC资源对象
     */
    public void close() {
        try {
            if (rs != null)
                rs.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            if (ps != null)
                ps.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            if (con != null)
                con.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }    
    }
}

调用示例

package cn.sxt.jdbc.demo3;

import cn.sxt.util.*;

public class Tester {

    /**
     * @param args
     */
    public static void main(String[] args) {
        DBUtil util = new DBUtil();
        //util.executeUpdate("delete from Dept");
        util.executeUpdate("insert into dept values(?,?,?)", 91,"i'm2","tjj");
    }

}
原文地址:https://www.cnblogs.com/Vincent-yuan/p/13128897.html