java JDBC

来源:互联网 发布:dz seo 编辑:程序博客网 时间:2024/06/13 23:24

1.什么是JDBC

通俗来讲JDBC技术就是通过java程序来发送SQL语句到数据库,数据库收到SQL语句后执行,把结果返回给java程序管理。

2.使用JDBC要有什么条件呢?

A)目标数据库主机的地址

B)数据库软件在该主机上所占用的端口号

C)登陆数据库用的用户名

D)该用户名的密码

E)连接数据库

3.JDBC技术的原理

我们知道,数据库是有各种类型的,不同的厂商生产的数据库标格和规范是不同的,这时候,如果我们用JAVA代码来发送SQL语句,就要根据不同的数据库来写一套又一套的操作代码,这对程序开发者的开发成本是十分巨大的,所以,SUN公司在开发JDBC技术的时候,规定了一套标准接口,数据库产商都必须提供一个驱动来实现这套接口,那么,只要程序开发者在开发时使用了该数据库的驱动,就用一致的方法来开发了,而不需自己写一套有一套的代码去适应不同的数据库。

4.JDBC中的核心API

|-Driver : 驱动程序类实现的接口。

|-Connectionconnect(String url, Properties info)  --用于连接数据库,得到连接对象

Properties里需要设置的参数:

url数据库连接的URL字符串。协议+数据库子协议+主机+端口+数据库

user数据库用户名

password用户的密码

|-Connection:    与数据库连接的接口

|-Statement createStatement()   --创建Statement对象,用于发送sql语句

|-PreparedStatement prepareStatement(String sql)  -创建PreparedStatement对象,用于发送预编译的sql语句

|-CallableStatementprepareCall(String sql)  --创建CallableStatement对象,用于调用存储过程。

|-Statement用于执行静态sql语句

|-intexecuteUpdate(String sql)  --执行更新操作(DDL+DML

|-ResultSetexecuteQuery(String sql)  --执行查询操作(DQL)

|-PreparedStatement用于执行预编译的sql语句

|-int executeUpdate() -- 执行更新操作

|-ResultSet executeQuery()    -- 执行查询操作

|-CallableStatement用于执行存储过程的sql

|-ResultSet executeQuery()  --调用存储过程

|-ResultSet结果集。用于封装数据库的查询后的数据

|-boolean next() --将记录光标移动到下一行

|-Object getObject(int columnIndex) -- 得到字段上的值

了解完又哪些API,下面我们就来使用JDBC发送SQL语句吧~

5.使用Statement对象操作数据库

DDLDML操作

步骤1

导包,因为我使用的是MySQL数据库,所以要使用JDBC技术,必须使用由MySQL数据库产商提供的数据库驱动,所以,第一步我们要把数据库驱动包导入工程里。

使用的包名:mysql-connector-java-5.1.7-bin.jar

步骤2

创建一个普通的类,在里面添加一个方法,在该方法中按照以下步骤

复制代码代码如下:

//URL
    private String url ="jdbc:mysql://localhost:3306/vmaxtam";
    //user
    private String user = "root";
    //password
    private String password = "root";

 

public void testDDL()throws Exception{
        //1.
注册驱动
       Class.forName("com.mysql.jdbc.Driver");
        
        //2.
获取连接
        Connection conn =DriverManager.getConnection(url, user, password);
        
        //3.
创建Statement对象
        Statement stmt =conn.createStatement();
        
        //4.
准备sql语句
        String sql  ="CREATE TABLEstudent(sid INT PRIMARY KEY,sname VARCHAR(20),age INT)";
        
        //5.
通过statement对象发送sql语句,返回执行结果
        int count = stmt.executeUpdate(sql);
        
        //6.
打印执行结果
        System.out.println("
影响了"+count+"条记录");
}
//7.
关闭资源
if(statement!=null)
{
    statement.close();
}

if(conn!=null)
{
    conn.close();
}


如果要进行DQLDDL操作,都可以把SQL语句写好,然后调用statementexecutlUpdate方法来给数据库执行SQL语句,这个方法返回一个整数值,表示数据库中有多少行受到了影响。

 

如果我们不改变上述的程序,想要再向数据库发出SQL语句,那么又要写一个程序来再次连接,操作完后又要关闭statement对象connection对象,这是十分繁琐的。所以,我们一般把连接过程和释放对象的过程抽取到一个工具类中。工具类中的代码如下:

复制代码代码如下:

public class sqlUtil {
    private static String url = "jdbc:mysql://localhost:3306/vmaxtam";
    private static String user = "root";
    private static String password = "root";

 

    // 获取连接
    public static Connection getconnection() {
        Connection conn = null;
        try {
            // 1.
注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2.
获取连接
            conn =DriverManager.getConnection(url, user, password);
            // 3.
获得statement对象
            Statementstatement = conn.createStatement();
        } catch (Exception e) {
            // TODOAuto-generated catch block
           e.printStackTrace();
        }
        return conn;
    }

    // 7.关闭资源
    public static void close(Statement statement, Connectionconnection) {
        {
            try {
               if (statement != null)
                   statement.close();
               if (connection != null) {
                   connection.close();
               }
            } catch(SQLException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
            }
        }
    }
}

 

还要考虑的情况就是:

一)一个用户只需要注册一次驱动就行,不用每次连接数据库都注册驱动,所以我们把注册驱动的过程写在静态代码块中。

二)url 和用户名,密码还有驱动类名,在程序里是写死的,为了能够在不改代码的前提下更换数据库或者更换用户,我们通常把这些信息写到一份配置文件中。

配置文件写在工程的src目录下,名为db.properties

复制代码代码如下:

url=jdbc:mysql://localhost:3306/vmaxtam
user=root
password=root
driverClass=com.mysql.jdbc.Drive


然后再sqlUtil中读取该配置文件,最后优化成下面代码

复制代码代码如下:

public class sqlUtil {
    private static String url = null;
    private static String user = null;
    private static String password = null;
    private static String driverClass= null;

 

    static{
        try {
            //1.
获得字节码对象
            Class clazz= sqlUtil.class;
            
            //2.
调用getResourceAsStream获取路径
            InputStreaminputStream = clazz.getResourceAsStream("/db.properties");
            Propertiespro = new Properties();
           pro.load(inputStream);
            
            //3.
读取参数
           url=pro.getProperty("url");
           password=pro.getProperty("password");
            user=pro.getProperty("user");
           driverClass=pro.getProperty("driverClass");
            
           Class.forName(driverClass);
        } catch (Exception e) {
           e.printStackTrace();
           System.out.println("
注册失败!" + e.getMessage());
            throw newRuntimeException(e);
        }
    }
    
    //
获取连接
    public static Connection getconnection() {
        Connection conn = null;
        try{        
            //
获取连接
            conn =DriverManager.getConnection(url, user, password);
            //
获得statement对象
            Statementstatement = conn.createStatement();
        } catch (Exception e) {
           e.printStackTrace();
        }
        return conn;
    }

    // 关闭资源
    public static void close(Statement statement, Connectionconnection) {
        {
            try {
               if (statement != null)
                   statement.close();
               if (connection != null) {
                   connection.close();
               }
            } catch(SQLException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
            }
        }
    }
}

 

DQL操作

那么如何用JDBC来查询数据库中的数据呢?

复制代码代码如下:

@Test
    public void testdsl() throws Exception {
        //
获取连接
        cnn2=sqlUtil.getconnection();
        Statement statement =cnn2.createStatement();
    
        
        //
准备SQL语句
        String sql = "select * fromsubject";
        
        //
调用executeQuery执行查询语句
        ResultSet res =statement.executeQuery(sql);
        
        //
查询结束后res会指向表头,想要获取数据必须不断地指向查询结果的下一行,当没有下一行数据时,返回0.
        while(res.next())
        {
            //
获取查询结果中字段为“sjid”的值,并且要明确类型
            int id =res.getInt("sjid");
            
            //
获取查询结果中字段为“sjname”的值,并且要明确类型
            String name= res.getString("sjname");
           System.out.println("ID:" + id + "  NAME:" + name);
        }
        sqlUtil.close(statement, cnn2);
}

 

以上就是使用Statement对象来操作数据库了~

6.使用PreparedStatement操作数据库

PreparedStatement对象其实就是一个特殊的Statement对象,它能够预编译SQL语句,当你把参数设置好,然后就可以去执行SQL语句了~

DDLDML操作

复制代码代码如下:

package com.vmaxtam.sqltest;

 

import java.sql.Connection;
import java.sql.PreparedStatement;

import org.junit.Test;

public class PreparedStatementTest {
    Connection connection = null;
    @Test
    public void ddldmlTest() throws Exception {
        // 1.
获取连接
        connection =sqlUtil.getconnection();

        // 2.准备SQL语句,预编译语句,参数用?号占位
        String sql = "INSERT INTOSUBJECT VALUES(?,?)";

        // 3.获得对象
        PreparedStatement preparedStatement= connection.prepareStatement(sql);

        /*
         * 4.
设置SQL参数需要参数是第几个,并且知道它的类型下面第一句表示:SQL语句第一个参数是int类型,参数值设置为3,如此类推
         */
        preparedStatement.setInt(1, 3);
        preparedStatement.setString(2,"
英语");

        // 5.交给数据库执行SQL
        int num =preparedStatement.executeUpdate();

       System.out.println("" + num + "条记录受到了影响");

             sqlUtil.close(preparedStatement , connection );
    }
}

 

以上就是使用PreparedStatement对象来进行插入语句的发送,同理,DDLDML类的语句都可以根据这样来发送.

PreparedStatement预编译的好处:

PreparedStatement的预编译可以使你可以通过设置不同的参数来查询不同的目标,在数据库端,只会保存一段预编译语句,但是如果你使用Statement来发送语句,每发送一条,数据库中就会存一条,这可能会造成占用大量内存。

DQL操作

复制代码代码如下:

@Test
    public void dqlTest() throws Exception {
        // 1.
获取连接
        connection =sqlUtil.getconnection();

 

        // 2.准备SQL语句,预编译语句,参数用?号占位
        String sql = "select * fromsubject where sjid=? or sjname=?";

        // 3.获得对象
        PreparedStatement preparedStatement= connection.prepareStatement(sql);

        /*
         * 4.
设置SQL参数需要参数是第几个,并且知道它的类型下面第一句表示:SQL语句第一个参数是int类型,参数值设置为3,如此类推
         */
        preparedStatement.setInt(1, 2);
        preparedStatement.setString(2,"
语文");

        // 5.交给数据库执行SQL
        ResultSet rst =preparedStatement.executeQuery();
        
        //6.
迭代结果集
        while(rst.next())
        {
            int id =rst.getInt("sjid");
            String name= rst.getString("sjname");
           System.out.println("ID:" + id + "  NAME:" + name);
        }
        
        //7.
关闭连接
        sqlUtil.close(preparedStatement,connection);
}

 

也是调用executeQuery();方法即可,得到结果集后迭代输出~

既然StatementPreparedStatement那么相似,比较它们的优缺点吧~

StatementPreparedStatement的区别:

1.语法不同

Statement只支持静态编译,SQL语句是写死的。

PreparedStatement支持预编译,用?号来占位。

2.效率不同

Statement每次都要发送一条SQL语句,不支持缓存,执行效率低。

PreparedStatement支持预编译,缓存在数据库,只需发送参数,执行效率快。

3.安全性不同

Statement容易被注入。

注入:狡猾的分子可以编写特殊的SQL语句来入侵数据库。

例如:要查询某个用户的信息

一般情况:SELECT *FROM user_list where username=xxx and password=xxx;(这里的xxx本应为用户填写自己的用户名和密码)

注入情况:SELECT *FROM user_list where username='abc' or 1=1 -- password=xxx;

这样1=1恒等,而且在password前加上了“--”号,后面的内容成为了注释不被执行。也就是说,这样就能不用密码地查询所有的用户信息。

PreparedStatement,因为规定了SQL语句中的参数,所以可以防止注入。

结论:建议使用PreparedStatement,因为它更快更安全

7.使用CallableStatement执行存储过程

使用CallableStatement只是执行存储过程,创建存储过程我们还是要在数据库内创建的。

步骤1

现在数据库建好一个存储过程:

复制代码代码如下:

DELIMITER $
CREATE PROCEDURE pro_add(IN a INT , IN b VARCHAR(20),OUT c INT)
BEGIN    
    SELECT * FROM SUBJECT WHERE sjid=a OR sjname=b;
    SET c=a+a+a+a;
END $

 

步骤2

利用java代码执行,并得到输出参数

复制代码代码如下:

@Test
public void calaST() throws Exception {
        //
获取连接
        connection= sqlUtil.getconnection();
        //
准备SQL语句
        String sql = "CALLpro_add(?,?,?)";
        
        //
得到callableStatement对象
        CallableStatement cbs =connection.prepareCall(sql);
        
        //
设置输入参数,和preparedStatement一样
        cbs.setInt(1, 3);
        cbs.setString(2, "
数学");
        
        /*
那么如何设置输出参数呢?
         *
需要注册输出参数!
         */
        cbs.registerOutParameter(3,java.sql.Types.INTEGER);//
需要使用内置对象来设置参数类型
        
        //
执行SQL语句
        cbs.executeQuery();
        
        //
利用getXXX方法得到相应位置的输出参数
        Integer num= cbs.getInt(3);
        
        System.out.println("a*4 is" + num);
        
             //
关闭资源
        sqlUtil.close(cbs, connection);
}

 

0 0