Java 数据库连接——JDBC

JDBC 全程是 Java Database Connectivity,是一种用于执行 SQL 语句的 Java API,它由一组用 Java 编写的类和接口组成,属于 Java EE 的一部分。


图:JDBC 处于数据库驱动和应用程序之间,为多种关系型数据库提供统一的访问

JDBC 使用分为 7 步:
0. 导入 JDBC 的驱动程序,在 java project 的 built-in path 中加入 mysql-connector-5.1.8.jar
1. 注册 JDBC 驱动程序,最常使用 Class.forName(“…”)
2. 创建 Connection 对象,依据数据库的 URL,调用 DriverManager.getConnection( ) 方法
3. 创建 Statement 对象,connection.createStatement()
4. 执行 SQL 操作,返回 ResultSet
5. 对 ResultSet 进行处理
6. 清理环境,释放资源


图:本博客使用的 Students 表是这样的。
我被一个小 BUG 折腾了一个小时:mysql 安装在我的虚拟机的 linux里面,我的 java 代码在 windows 的 eclipse 里面。我的步骤 2,创建 connection 部分一直失败。最后终于发现,我的linux 里面的 mysql 不允许远程访问。。。最后通过百度,更改 mysql 配置解决了。


show me the code

Statement

package jdbc_test;

import java.sql.*;

public class mysql_jdbc_test
{
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";               // JDBC 驱动名称
    static final String DB_URL = "jdbc:mysql://192.168.1.108:3306/EXAMPLE?"; // URL,IP地址:mysql端口/数据库名
    static final String USER = "...";
    static final String PASSWORD = "...";

    public static void main(String[] args)
    {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try
        {
            Class.forName(JDBC_DRIVER);                                        // 步骤 1
            connection = DriverManager.getConnection(DB_URL, USER, PASSWORD);  // 步骤 2
            statement = connection.createStatement();                          // 步骤 3
            String sql = "SELECT id, name, age FROM Students";
            resultSet = statement.executeQuery(sql);  // 步骤 4

            while (resultSet.next())                  // 步骤 5
            {
                int id = resultSet.getInt("id");
                int age = resultSet.getInt("age");
                String name = resultSet.getString("name");

                System.out.print("ID: " + id);
                System.out.print(", Age: " + age);
                System.out.print(", Name: " + name);
                System.out.println();
            }

        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally  // 步骤 6
        {
            try
            {
                if (resultSet != null)
                {
                    resultSet.close();
                    resultSet = null;
                }
                if (statement != null)
                {
                    statement.close();
                    statement = null;
                }
                if (connection != null)
                {
                    connection.close();
                    connection = null;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

PreparedStatement

PreparedStatement 比单纯的 Statement 更好用,也用的更多,前者接口是后者接口的扩展。有利于执行多次使用的 SQL 语句,节省 String sql 的个数,可以灵活指定 SQL 语句中的变量。SQL语句中,用 ’ ? ’ 代表变量,占个位置。然后使用 setInt( ),setString( ) 设置参数。

PreparedStatement 和 Statement 两者相差的“prepared”,从代码层面可以看出来:connection 返回 PreparedStatement 对象的方法需要参数“带?的sql 语句”,connection 返回 Statement 对象的方法不需要参数。

package jdbc_test;

import java.sql.*;

public class PreparedStmt
{
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://192.168.1.108:3306/EXAMPLE";
    static final String USER = "...";
    static final String PASSWORD = "...";

    public static void main(String[] args)
    {
        Connection connection = null;
        PreparedStatement pStatement = null;
        ResultSet rSet = null;
        try
        {
            Class.forName(JDBC_DRIVER);
            connection = DriverManager.getConnection(DB_URL, USER, PASSWORD);

            String sql = "UPDATE Students set age = ? WHERE id = ?";
            pStatement = connection.prepareStatement(sql);
            pStatement.setInt(1, 20);
            pStatement.setInt(2, 1);

            sql = "SELECT id, name, age FROM Students";
            rSet = pStatement.executeQuery(sql);

            while (rSet.next())
            {
                int id = rSet.getInt("id");
                int age = rSet.getInt("age");
                String name = rSet.getString("name");

                System.out.print("ID: " + id);
                System.out.print(", Age: " + age);
                System.out.print(", Name: " + name);
                System.out.println();
            }
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (rSet != null)
                {
                    rSet.close();
                    rSet = null;
                }
                if (pStatement != null)
                {
                    pStatement.close();
                    pStatement = null;
                }
                if (connection != null)
                {
                    connection.close();
                    connection = null;
                }
            }
            catch (Exception e2)
            {
                e2.printStackTrace();
            }
        }
    }
}

进阶

DML:Database Manipulate Language,数据库操纵语言,就是 update, insert, delete。JDBC 中用 connection.executeUpdate( ) 一个方法统一了三种操纵方式。

CallableStatement:对存储过程进行调用。参数类型有三种:IN, OUT, INOUT。
IN       :setXXX( … )
OUT    :getXXX( … )
INOUT:同时提供输入和输出参数,setXXX( … ) + getXXX( .. )

ResultSet:由查询语句生成,表示数据库查询结果的数据表。ResultSet默认不可更新,仅有一个向前移动的指针,该指针初始位置在第一行之前。如果不默认的话,可以有很多设置,比如:游标指针可以前后移动,结果集是否可以即时更新,是否可以更新。是的注意的是:JDBC 提供了这些接口,但是数据库厂商(MySql,Oracle 等)不一定都去实现。
创建 ResultSet 的参数设置细节,实验楼网站课程

Transaction:运用事物处理。默认情况下,JDBC 连接是在自动提交模式下的。一个 Transaction 把一个SQL 或者多个 SQL 作为一个逻辑单元,保证这个逻辑单元里面的所有 SQL 语句在同一时间共同执行。要么一起成功,要么一起失败。如果失败,则整个事物回滚。好处是:提高程序运行的性能,保持业务流程的完整性,使用分布式业务管理方式。
connection.setAutoCommit(false);
connection.commit( );
connection.rollback(); ( catch 语句里面,出现异常,撤销事务 )

Batch:批处理。把相关的 SQL 语句组合成一个批处理和一个调用数据库提交。当一次发送多个 SQL 语句到数据库,可以减少通信开销。
addBatch( … )
executeBatch( … )
commit( )
批处理和事务代码样例

RowSet:默认是一个可滚动,可更新,可序列化的结果集。RowSet 的离线操作能有效的利用计算机的内存,减轻数据库服务器的负担。数据操作在内存中操作,然后批量提交到数据源,灵活性和性能都得到了很大的提高。RowSet 从 ResultSet 继承,支持断开结果集,支持 JavaBean

DataSource: DriverManager 的代替,在内部通过一个的机制来复用数据库连接,这样大大的减少了创建数据库连接的次数,提高了系统性能。连接池实现,分布式实现,DataSource 属性可以动态改变

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章