Java——JDBC

今天给大家更新一篇我自己学习Java——JDBC的经验

 

Java中JDBC是(Java DataBase Connectivity)的简称,由java语言编写的类和接口组成,可为多种关系型数据库提供了统一访问。

Sun公司(现被Oracle公司收购)提供了JDBC的接口规范——JDBC API,而数据库厂商和第三方中间件根据JDBC接口规范提供了不同数据库的具体实现——JDBC驱动。

 

JDBC API:提供各种不同数据库交互的标准接口,如Connection接口、PreparedStatement接口等,供开发人员使用JDBC接口进行各数据库的操作。

 

JDBC API主要做:与数据库建立连接、发送SQL语句、处理结果

DriverManager类:根据数据库的不同,管理相应的JDBC驱动   注:它位于JDK的java.sql包中

Connection接口:负责连接数据库并担任传输数据的任务

Statement接口:位于Connection接口中,负责执行SQL语句

PreparedStament接口:Statement的子接口,同样负责执行SQL语句,但它比Statement的具有更好的安全性、高性能、高效率及可维护性的优点。开发中推荐使用此接口,因PreparedStatement它使用的是预编译语句,不会和以预编译的SQL语句进行拼接,避免了SQL的注入。具体可看源代码Connection接口中PreparedStatement prepareStatement(String sql)的注解

ResultSet接口:负责保存和Statement或者PreparedStatement执行后所产生的查询结果

 

Connection接口有两种连接方式:JDBC-ODBC桥接和纯Java驱动

JDBC-ODBC:它通过ODBC与数据库进行连接

纯Java驱动:它直接同数据库进行连接,由JDBC驱动直接访问数据库,具跨平台特点。但由于技术原因需要数据库厂商和第三方中间件自己提供JDBC驱动。   注:此类JDBC驱动只对应一种类型数据库,且当数据库进行升级后,有些需要进行更换JDBC驱动

驱动版本不匹配又是运行时会报version本版的错误,如下注意红框处(version 51.0):

Java——JDBC

 

 

 一般决解此问题,更换相匹配的jdk

常见version和jdk匹配版本如下:

version 52.0        JDK 8.0(也可以理解为JDK1.8)

version 51.0        JDK 7.0(也可以理解为JDK1.7)

version 50.0        JDK 1.6

version 49.0        JDK 1.5

 

接下来,来一个纯java建立连接并关闭的示例

此示例需要注意:我使用的是sqlserver数据库,并且需要下载Java——JDBCsqlserver数据库的JDBC驱动

在使用Connection建立连接和关闭各连接是需要加长try{}catch{}进行捕获异常并处理一场,或者将他继续往上抛异常,(异常可以看上一篇的讲解),否则会报如:Unhandled exception:java.SQLException

 

Java——JDBC

 

 

 

 

报此错误原因是因为在DriverManager源代码类中,它的方法声明了一个SQLException的一个异常,所以此时需要我们进行处理此异常,具体代码如图下:

Java——JDBC

 

示例代码:

DemoOneTest.class

import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;public class DemoOneTest {    public static void main(String[] args) {        /**         * 使用jdbc纯java的方式建立连接         */        Connection conn = null;        //加载驱动        try {            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        //建立连接        try {            conn = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=自己数据库的名称", "sa", "123456");            if(null != conn){                System.out.println("建立连接!!!");            }else{                System.out.println("建立失败!!!");            }        } catch (SQLException e) {            e.printStackTrace();        } finally {            //关闭连接            try {                if (null != conn) {                    conn.close();                    System.out.println("关闭连接成功!!!");                }            } catch (SQLException e) {                e.printStackTrace();            }        }    }}

 

编程的习惯,在我们执行使用完数据库后,最好将它的连接关闭进行释放资源,这样会提高项目的性能

 

大家都已经练习了,示例一进行数据库的连接和关闭,我们在说一下PreparedStatement对象,之后使用PreparedStatement进行数据库的增、删、改、查、操作吧

 

创建PreparedStatement对象:通过Connection接口的preparedStatement(String sql)方法来进行PreparedStatment对象,SQL语句可具有一个或者多个输入参数。而这些参数的值都是在SQL语句创建时未指定的,此时我们可以使用?为每个输入的参数作为占位符。为什么会这样,请看Connection接口的源代码,图片如下

Java——JDBC

 

 

 

 

设置SQL中每个输入参数的值:通过setXxx()方法来完成。Xxx是与该参数相对应的类型。如:参数为String类型,我们则使用方法为setString().

注意的是setXxx()方法中,会有两个参数是(int parameterIndex, String x

int paramenterIndex:此参数类型说的是“?”占位符的序号位置(从1开始)

String x :此参数类型说的是,为占位符设置参数的值

具体来源可看如下图片,根据PreparedStatemnt源代码的方法和注解得来的

Java——JDBC

 

执行SQL语句:设置完了输入的参数后,我们可以使用PreparedStatement接口的3个执行方法:

1:ResultSet executeQuery():可以执行SQL查询并获得ResultSet对象

 Java——JDBC

 

 

 

2:int executeUpdate():可以执行增加、删除、更新操作,返回值为执行该操作所影响的行数

Java——JDBC

 

 

 

3:boolean execute():可以执行SQL语句,若结果为ResultSet对象,则返回true;若更新计数或者不存在任何结果,则返回false;

Java——JDBC

 

 

 

 

如上介绍了PreparedStatement对象,下面写增、删、改、查的示例了。

 

使用PreparedStatement对象,增加示例:

Department.class

public class Department {    private int departmentId;    private String departmentName;    public void setDepartmentId(int departmentId){        this.departmentId = departmentId;    }    public int getDepartmentId(){        return departmentId;    }    public void setDepartmentName(String departmentName){        this.departmentName = departmentName;    }    public String getDepartmentName(){        return departmentName;    }}

DemoThreeTest.class

import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.SQLException;public class DemoThreeTest {    public static void main(String[] args){        Connection connection = null;        PreparedStatement ps = null;        Department department = new Department();        /**         * 加载驱动         */        try {            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");        }catch (Exception e){            e.printStackTrace();        }        /**         * 建立连接         */        try {            connection = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=Company", "sa", "123456");            String sql = "insert into Department (departmentId,departmentName)  values (?,?)";            ps = connection.prepareStatement(sql);            department.setDepartmentId(5);            department.setDepartmentName("研发部");            ps.setInt(1,department.getDepartmentId());            ps.setString(2,department.getDepartmentName());            int id = ps.executeUpdate();            if(id > 0){                System.out.println("插入成功!!!");            }            else{                System.out.println("插入失败!!!");            }        } catch (SQLException e) {            e.printStackTrace();        }finally {            try {                if(ps != null){                    ps.close();                    System.out.println("PrepareStatement关闭连接!!!");                }                if(connection != null){                    connection.close();                    System.out.println("Connection关闭连接!!!");                }            }catch (Exception e){                e.printStackTrace();            }        }    }}结果如下:
使用PreparedStatement对象,删除示例:DemoFourTest.Class
import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.SQLException;public class DemoFourTest {    public static void main(String[] args){        Connection connection = null;        PreparedStatement ps = null;        Department department = new Department();        /**         * 加载驱动         */        try {            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");        }catch (Exception e){            e.printStackTrace();        }        /**         * 建立连接         */        try {            connection = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=Company", "sa", "123456");            String sql = "delete Department where departmentId = ?";            ps = connection.prepareStatement(sql);            department.setDepartmentId(5);            ps.setInt(1,department.getDepartmentId());            int id = ps.executeUpdate();            if(id > 0){                System.out.println("删除成功!!!");            }            else{                System.out.println("删除失败!!!");            }        } catch (SQLException e) {            e.printStackTrace();        }finally {            try {                if(ps != null){                    ps.close();                    System.out.println("PrepareStatement关闭连接!!!");                }                if(connection != null){                    connection.close();                    System.out.println("Connection关闭连接!!!");                }            }catch (Exception e){                e.printStackTrace();            }        }    }}
结果如下:
使用PreparedStatement对象,修改示例:DemoFive.Class
import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.SQLException;public class DemoFiveTest {    public static void main(String[] args){        Connection connection = null;        PreparedStatement ps = null;        Department department = new Department();        /**         * 加载驱动         */        try {            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");        }catch (Exception e){            e.printStackTrace();        }        /**         * 建立连接         */        try {            connection = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=Company", "sa", "123456");            String sql = "update Department set departmentName = ? where departmentId = ?";            ps = connection.prepareStatement(sql);            department.setDepartmentId(3);            department.setDepartmentName("营销部");            ps.setString(1,department.getDepartmentName());            ps.setInt(2,department.getDepartmentId());            int id = ps.executeUpdate();            if(id > 0){                System.out.println("修改成功!!!");            }            else{                System.out.println("修改失败!!!");            }        } catch (SQLException e) {            e.printStackTrace();        }finally {            try {                if(ps != null){                    ps.close();                    System.out.println("PrepareStatement关闭连接!!!");                }                if(connection != null){                    connection.close();                    System.out.println("Connection关闭连接!!!");                }            }catch (Exception e){                e.printStackTrace();            }        }    }}
结果如下:
使用PreparedStatement对象,查询示例:DemoSixTest.Class
import java.sql.*;public class DemoSixTest {    public static void main(String[] args){        Connection connection = null;        PreparedStatement ps = null;        ResultSet rs = null;        Department department = new Department();        /**         * 加载驱动         */        try {            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");        }catch (Exception e){            e.printStackTrace();        }        /**         * 建立连接         */        try {            connection = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=Company", "sa", "123456");            String sql = "select departmentId, departmentName from department";            ps = connection.prepareStatement(sql);            rs = ps.executeQuery();            if(rs!=null){                while(rs.next()){                    System.out.print(rs.getInt("departmentId")+"\t");                    System.out.println(rs.getString("departmentName"));                }            }        } catch (SQLException e) {            e.printStackTrace();        }finally {            try {                if(rs!= null){                    rs.close();                    System.out.println("ResultSet关闭连接!!!");                }                if(ps != null){                    ps.close();                    System.out.println("PrepareStatement关闭连接!!!");                }                if(connection != null){                    connection.close();                    System.out.println("Connection关闭连接!!!");                }            }catch (Exception e){                e.printStackTrace();            }        }    }}
结果如下:

 

 

好了,刚刚大家看了也练习了这么多的代码,最后给大家讲一下大家都想了解的,SQL注入

为什么会有SQL注入攻击,原因是在使用Statment接口方法时要进行SQL语句的拼接,并且每次调用方法执行SQL语句时,都要进行SQL语句的解析和编译操作,导致可以对SQL截取后注入

 

具体示例如下:

DemoSevenTest.class

import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;import java.util.Scanner;public class DemoSevenTest {    public static void main(String[] args){        Connection connection= null;        Statement statement = null;        Department department = new Department();        ResultSet rs = null;        //根据控制台提示输入部门ID和部门名称        Scanner input = new Scanner(System.in);        System.out.println("请输入部门ID:");        int departmentId = input.nextInt();        System.out.println("请输入部门名称:");        String departmentName = input.next();        /**         * 加载驱动         */        try {            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        /**         * 建立连接         */        try {            connection = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=Company", "sa", "123456");            department.setDepartmentId(departmentId);            department.setDepartmentName(departmentName);            //判断是否正确            statement = connection.createStatement();            String sql = "select departmentId, departmentName from department where departmentId = ‘"+department.getDepartmentId()+"‘ and departmentName = ‘"+department.getDepartmentName()+"‘";            rs = statement.executeQuery(sql);            if(rs!=null){                if(rs.next()){                    System.out.println("部门ID和部门名称正确!!!");                }else{                    System.out.println("部门ID和部门名称不正确!!!");                }            }        }catch (Exception e){            e.printStackTrace();        }    }}结果情况:正确

 

 结果情况:错误

Java——JDBC

 

 当我使用SQL注入,在执行结果情况:错误的,再看一下

Java——JDBC

 

 其上就是典型的SQL注入攻击!!!

 

谢谢!!!

 

相关推荐