JDBC編程


SQL語句主要分為五種:

1. 查詢語句:主要由select關鍵字完成,查詢語句是SQL語句中最復雜、功能最豐富的語句;

2. DML(Data Manipulation Language,數據操作語言):包含insert、update、delete

3. DDL(Data Definition Language, 數據定義語言):包含create、 alter、drop、truncate

4. DCL(Data Control Language,數據控制語言):包含grant 、revoke

5. 事務控制語句: commit、rollback、savepoint

 

JDBC編程步驟:

1. 加載數據庫驅動。通過Class類的forName()靜態方法來加載驅動

Class.forName(driverClass)

2. 通過DriverManager獲取數據庫連接Connection對象。

DriverManager.getConnection(String url,String user,String pass)

3. 通過Connection對象創建Statement對象。創建Statement有三種方法。

  • createStatement(): 創建基本的Statement對象
  • prepareStatement(String sql): 根據傳入的SQL語句創建預編譯的Statement對象
  • prepareCall(String sql): 根據傳入的SQL語句創建CallableStatement對象。

4. 使用Statement執行SQL語句。

execute(): 可以執行任何SQL語句,但比較麻煩,在不清SQL語句類型時,只能使用這個方法。

executeUpdate():主要用於執行DML和DDL語句。執行DML語句返回受SQL語句影響的行數,執行DDL語句返回0。

executeQuery():只能執行查詢語句,執行后返回代表查詢結果的ResultSet對象。

5. 操作結果集。有兩類方法來操作結果集:

  • next()、 previous()、 first()、 last()、 beforeFirst()、 afterLast()、 absolute()
  • getXxx()方法獲取記錄指針指向行、特定列的值。

6. 回收數據庫資源,包括ResultSet、Statement和Connection等資源。

例子:

import java.sql.*;

public class ConnMySql
{
    public static void main(String[] args) throws Exception
    {
        // 1.加載驅動,使用反射的知識,現在記住這么寫。
        Class.forName("com.mysql.jdbc.Driver");
        try(
            // 2.使用DriverManager獲取數據庫連接,
            // 其中返回的Connection就代表了Java程序和數據庫的連接
            // 不同數據庫的URL寫法需要查驅動文檔知道,用戶名、密碼由DBA分配
            Connection conn = DriverManager.getConnection(
                "jdbc:mysql://127.0.0.1:3306/select_test"
                , "root" , "32147");
            // 3.使用Connection來創建一個Statment對象
            Statement stmt = conn.createStatement();
            // 4.執行SQL語句
            /*
            Statement有三種執行sql語句的方法:
            1 execute 可執行任何SQL語句。- 返回一個boolean值,
              如果執行后第一個結果是ResultSet,則返回true,否則返回false
            2 executeQuery 執行Select語句 - 返回查詢到的結果集
            3 executeUpdate 用於執行DML語句。- 返回一個整數,
              代表被SQL語句影響的記錄條數
            */
            ResultSet rs = stmt.executeQuery("select s.* , teacher_name"
                + " from student_table s , teacher_table t"
                + " where t.teacher_id = s.java_teacher"))//在try語句中,執行完后會自動關閉。
        {
            // ResultSet有系列的getXxx(列索引 | 列名),用於獲取記錄指針
            // 指向行、特定列的值,不斷地使用next()將記錄指針下移一行,
            // 如果移動之后記錄指針依然指向有效行,則next()方法返回true。
            while(rs.next())
            {
                System.out.println(rs.getInt(1) + "\t"
                    + rs.getString(2) + "\t"
                    + rs.getString(3) + "\t"
                    + rs.getString(4));
            }
        }
    }
}
View Code

 

 執行DDL語句的例子:

import java.util.*;
import java.io.*;
import java.sql.*;

public class ExecuteDDL
{
    private String driver;
    private String url;
    private String user;
    private String pass;
    public void initParam(String paramFile)
        throws Exception
    {
        // 使用Properties類來加載屬性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }
    public void createTable(String sql)throws Exception //注意這個返回值類型
    {
        // 加載驅動
        Class.forName(driver);
        try(
        // 獲取數據庫連接
        Connection conn = DriverManager.getConnection(url , user , pass);
        // 使用Connection來創建一個Statment對象
        Statement stmt = conn.createStatement())
        {
            // 執行DDL,創建數據表
            stmt.executeUpdate(sql);
        }
    }
    public static void main(String[] args) throws Exception
    {
        ExecuteDDL ed = new ExecuteDDL();
        ed.initParam("mysql.ini");
        ed.createTable("create table jdbc_test "
            + "( jdbc_id int auto_increment primary key, "
            + "jdbc_name varchar(255), "
            + "jdbc_desc text);");
        System.out.println("-----建表成功-----");
    }
}
View Code

 

執行DML語句的例子 :

import java.util.*;
import java.io.*;
import java.sql.*;

public class ExecuteDML
{
    private String driver;
    private String url;
    private String user;
    private String pass;

    public void initParam(String paramFile)
        throws Exception
    {
        // 使用Properties類來加載屬性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }
    public int insertData(String sql)throws Exception//注意這里的返回值類型
    {
        // 加載驅動
        Class.forName(driver);
        try(
            // 獲取數據庫連接
            Connection conn = DriverManager.getConnection(url
                , user , pass);
            // 使用Connection來創建一個Statment對象
            Statement stmt = conn.createStatement())
        {
            // 執行DML,返回受影響的記錄條數
            return stmt.executeUpdate(sql);
        }
    }
    public static void main(String[] args)throws Exception
    {
        ExecuteDML ed = new ExecuteDML();
        ed.initParam("mysql.ini");
        int result = ed.insertData("insert into jdbc_test(jdbc_name,jdbc_desc)"
            + "select s.student_name , t.teacher_name "
            + "from student_table s , teacher_table t "
            + "where s.java_teacher = t.teacher_id;");
        System.out.println("--系統中共有" + result + "條記錄受影響--");
    }
}
View Code

 當不清楚SQL語句類型時的例子:

 

import java.util.*;
import java.io.*;
import java.sql.*;

public class ExecuteSQL
{
    private String driver;
    private String url;
    private String user;
    private String pass;
    public void initParam(String paramFile)throws Exception
    {
        // 使用Properties類來加載屬性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }
    public void executeSql(String sql)throws Exception
    {
        // 加載驅動
        Class.forName(driver);
        try(
            // 獲取數據庫連接
            Connection conn = DriverManager.getConnection(url
                , user , pass);
            // 使用Connection來創建一個Statement對象
            Statement stmt = conn.createStatement())
        {
            // 執行SQL,返回boolean值表示是否包含ResultSet
            boolean hasResultSet = stmt.execute(sql);
            // 如果執行后有ResultSet結果集
            if (hasResultSet)
            {
                try(
                    // 獲取結果集
                    ResultSet rs = stmt.getResultSet())
                {
                    // ResultSetMetaData是用於分析結果集的元數據接口
                    ResultSetMetaData rsmd = rs.getMetaData();
                    int columnCount = rsmd.getColumnCount();
                    // 迭代輸出ResultSet對象
                    while (rs.next())
                    {
                        // 依次輸出每列的值
                        for (int i = 0 ; i < columnCount ; i++ )
                        {
                            System.out.print(rs.getString(i + 1) + "\t");
                        }
                        System.out.print("\n");
                    }
                }
            }
            else
            {
                System.out.println("該SQL語句影響的記錄有"
                    + stmt.getUpdateCount() + "條");
            }
        }
    }
    public static void main(String[] args) throws Exception
    {
        ExecuteSQL es = new ExecuteSQL();
        es.initParam("mysql.ini");
        System.out.println("------執行刪除表的DDL語句-----");
        es.executeSql("drop table if exists my_test");
        System.out.println("------執行建表的DDL語句-----");
        es.executeSql("create table my_test"
            + "(test_id int auto_increment primary key, "
            + "test_name varchar(255))");
        System.out.println("------執行插入數據的DML語句-----");
        es.executeSql("insert into my_test(test_name) "
            + "select student_name from student_table");
        System.out.println("------執行查詢數據的查詢語句-----");
        es.executeSql("select * from my_test");
    }
}
View Code

 

使用PreparedStatement執行SQL語句的例子(使用這種方法,可以防止SQL注入,比如在登錄框中輸入‘or true or’)

import java.util.*;
import java.io.*;
import java.sql.*;

public class PreparedStatementTest
{
    private String driver;
    private String url;
    private String user;
    private String pass;
    public void initParam(String paramFile)throws Exception
    {
        // 使用Properties類來加載屬性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
        // 加載驅動
        Class.forName(driver);
    }
    public void insertUseStatement()throws Exception
    {
        long start = System.currentTimeMillis();
        try(
            // 獲取數據庫連接
            Connection conn = DriverManager.getConnection(url
                , user , pass);
            // 使用Connection來創建一個Statment對象
            Statement stmt = conn.createStatement())
        {
            // 需要使用100條SQL語句來插入100條記錄
            for (int i = 0; i < 100 ; i++ )
            {
                stmt.executeUpdate("insert into student_table values("
                    + " null ,'姓名" + i + "' , 1)");
            }
            System.out.println("使用Statement費時:"
                + (System.currentTimeMillis() - start));
        }
    }
    public void insertUsePrepare()throws Exception
    {
        long start = System.currentTimeMillis();
        try(
            // 獲取數據庫連接
            Connection conn = DriverManager.getConnection(url
                , user , pass);
            // 使用Connection來創建一個PreparedStatement對象
            PreparedStatement pstmt = conn.prepareStatement(
                "insert into student_table values(null,?,1)"))

        {
            // 100次為PreparedStatement的參數設值,就可以插入100條記錄
            for (int i = 0; i < 100 ; i++ )
            {
                pstmt.setString(1 , "姓名" + i);
                pstmt.executeUpdate();
            }
            System.out.println("使用PreparedStatement費時:"
                + (System.currentTimeMillis() - start));
        }
    }
    public static void main(String[] args) throws Exception
    {
        PreparedStatementTest pt = new PreparedStatementTest();
        pt.initParam("mysql.ini");
        pt.insertUseStatement();
        pt.insertUsePrepare();
    }
}
View Code

 

使用CallableStatement調用存儲過程的例子

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.sql.*;

public class CallableStatementTest
{
    private String driver;
    private String url;
    private String user;
    private String pass;
    public void initParam(String paramFile)throws Exception
    {
        // 使用Properties類來加載屬性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }
    public void callProcedure()throws Exception
    {
        // 加載驅動
        Class.forName(driver);
        try(
            // 獲取數據庫連接
            Connection conn = DriverManager.getConnection(url
                , user , pass);
            // 使用Connection來創建一個CallableStatment對象
            CallableStatement cstmt = conn.prepareCall(
                "{call add_pro(?,?,?)}"))
        {
            cstmt.setInt(1, 4);
            cstmt.setInt(2, 5);
            // 注冊CallableStatement的第三個參數是int類型
            cstmt.registerOutParameter(3, Types.INTEGER);
            // 執行存儲過程
            cstmt.execute();
            // 獲取,並輸出存儲過程傳出參數的值。
            System.out.println("執行結果是: " + cstmt.getInt(3));
        }
    }
    public static void main(String[] args) throws Exception
    {
        CallableStatementTest ct = new CallableStatementTest();
        ct.initParam("mysql.ini");
        ct.callProcedure();
    }
}
View Code

 

 

 

管理結果集:


可滾動、可更新的結果集

需要在創建Statement或者PrepareStatement時傳入額外的參數,如下面例子:

import java.util.*;
import java.io.*;
import java.sql.*;

public class ResultSetTest
{
    private String driver;
    private String url;
    private String user;
    private String pass;
    public void initParam(String paramFile)throws Exception
    {
        // 使用Properties類來加載屬性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }
    public void query(String sql)throws Exception
    {
        // 加載驅動
        Class.forName(driver);
        try(
            // 獲取數據庫連接
            Connection conn = DriverManager.getConnection(url , user , pass);
            // 使用Connection來創建一個PreparedStatement對象
            // 傳入控制結果集可滾動,可更新的參數。
            PreparedStatement pstmt = conn.prepareStatement(sql
                , ResultSet.TYPE_SCROLL_INSENSITIVE
                , ResultSet.CONCUR_UPDATABLE);
            ResultSet rs = pstmt.executeQuery())
        {
            rs.last();
            int rowCount = rs.getRow();
            for (int i = rowCount; i > 0 ; i-- )
            {
                rs.absolute(i);
                System.out.println(rs.getString(1) + "\t"
                    + rs.getString(2) + "\t" + rs.getString(3));
                // 修改記錄指針所有記錄、第2列的值
                rs.updateString(2 , "學生名" + i);
                // 提交修改
                rs.updateRow();
            }
        }
    }
    public static void main(String[] args) throws Exception
    {
        ResultSetTest rt = new ResultSetTest();
        rt.initParam("mysql.ini");
        rt.query("select * from student_table");
    }
}
View Code

 


處理Blob類型數據

Blob(Binary Long object)是二進制長對象的意思。使用該類可以吧圖片、聲音等文件的二進制數據保存在數據庫中,並可以從數據庫中恢復指定文件。

通過PrepareStatement的setBinaryStream(int parameterIndex,InputStream x),該方法可以指定參數傳入二進制流。

如果需要從ResultSet中取出Blob數據,可以調用ResultSet的getBlob(int columnIndex)來返回一個Blob對象,然后再通過Blob對象的getBinaryStream()方法獲取該Blob數據的輸入流,也可以使用Blob對象的getBytes()方法直接讀取該Blob對象封裝的二進制數據。

 

使用ResultSetMetaData分析結果集:

 

該對象可以通過ResultSet的getMetaData()方法來放回。常用的方法有:

  • int getColumnCount():返回該ResultSet的列數量
  • String getColumnName(int column):返回指定索引的列名
  • int getColumnType(int column):返回指定索引的列類型

事務處理

 事務是由一步或幾步數據庫操作序列組成的邏輯執行單元,這系列操作要么全部執行,要么全部放棄執行。

事務有四個特性:原子性、一致性、隔離性、持續性。

 

數據庫事務由下列語句組成。

一組DML語句,一條DDL語句,一條DCL語句。DDL和DCL語句最多只能有一條,因為DDL和DCL語句都會導致事務立即提交。

 

事務提交方式(沒有提交前事務中的語句不會生效)

1.顯式提交:使用commit

2.自動提交:執行DDL或DCL語句,或者程序正常退出。

 

 

 

事務回滾方式:(沒有生效的事務可以回滾)

1.顯式回滾:使用rollback

2.自動回滾:系統錯誤或者強行退出

 

自動提交和開始事務是對立的,開始事務功能后,就會將自動提交的功能關閉。正常情況下需要手動關閉自動提交。

 

JDBC對事務的支持

可以調用Connection的setAutoCommit()方法來關閉自動提交,開啟事務。getAutoCommit()返回自動提交模式。commit()提交事務。rollback()回滾事務。

例子:

import java.sql.*;
import java.io.*;
import java.util.*;

public class TransactionTest
{
    private String driver;
    private String url;
    private String user;
    private String pass;
    public void initParam(String paramFile)throws Exception
    {
        // 使用Properties類來加載屬性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }
    public void insertInTransaction(String[] sqls) throws Exception
    {
        // 加載驅動
        Class.forName(driver);
        try(
            Connection conn = DriverManager.getConnection(url , user , pass))
        {
            // 關閉自動提交,開啟事務
            conn.setAutoCommit(false);
            try(
                // 使用Connection來創建一個Statment對象
                Statement stmt = conn.createStatement())
            {
                // 循環多次執行SQL語句
                for (String sql : sqls)
                {
                    stmt.executeUpdate(sql);
                }
            }
            // 提交事務
            conn.commit();
        }
    }
    public static void main(String[] args) throws Exception
    {
        TransactionTest tt = new TransactionTest();
        tt.initParam("mysql.ini");
        String[] sqls = new String[]{
            "insert into student_table values(null , 'aaa' ,1)",
            "insert into student_table values(null , 'bbb' ,1)",
            "insert into student_table values(null , 'ccc' ,1)",
            // 下面這條SQL語句將會違反外鍵約束,
            // 因為teacher_table中沒有ID為5的記錄。
            "insert into student_table values(null , 'ccc' ,5)" //
        };
        tt.insertInTransaction(sqls);
    }
}
View Code

 

使用DatabaseMetaData分析數據庫信息

通過Connection提供的getMetaData()方法獲取DatabaseMetaData對象。許多DatabaseMetaData方法是以ResultSet對象的形式返回查詢信息,然后使用ResultSet中的常規方法獲取內容。如果沒有內容就返回一個空的ResultSet對象。

DatabaseMetaData的許多方法都需要傳入一個xxxPattern模式字符串,這里的xxxPattern不是正則表達式,而是SQL里的模式字符串。

即用百分號(%)代表任意多個字符,使用下划線(_)代表一個字符。通常情況下,如果把該模式字符串的參數值設置為null,即表明該參數不過為過濾條件。

例子:

import java.sql.*;
import java.util.*;
import java.io.*;

public class DatabaseMetaDataTest
{
    private String driver;
    private String url;
    private String user;
    private String pass;
    public void initParam(String paramFile)throws Exception
    {
        // 使用Properties類來加載屬性文件
        Properties props = new Properties();
        props.load(new FileInputStream(paramFile));
        driver = props.getProperty("driver");
        url = props.getProperty("url");
        user = props.getProperty("user");
        pass = props.getProperty("pass");
    }
    public void info() throws Exception
    {
        // 加載驅動
        Class.forName(driver);
        try(
            // 獲取數據庫連接
            Connection conn = DriverManager.getConnection(url
                , user , pass))
        {
            // 獲取的DatabaseMetaData對象
            DatabaseMetaData dbmd = conn.getMetaData();
            // 獲取MySQL支持的所有表類型
            ResultSet rs = dbmd.getTableTypes();
            System.out.println("--MySQL支持的表類型信息--");
            printResultSet(rs);
            // 獲取當前數據庫的全部數據表
            rs = dbmd.getTables(null,null, "%" , new String[]{"TABLE"});
            System.out.println("--當前數據庫里的數據表信息--");
            printResultSet(rs);
            // 獲取student_table表的主鍵
            rs = dbmd.getPrimaryKeys(null , null, "student_table");
            System.out.println("--student_table表的主鍵信息--");
            printResultSet(rs);
            // 獲取當前數據庫的全部存儲過程
            rs = dbmd.getProcedures(null , null, "%");
            System.out.println("--當前數據庫里的存儲過程信息--");
            printResultSet(rs);
            // 獲取teacher_table表和student_table之間的外鍵約束
            rs = dbmd.getCrossReference(null,null, "teacher_table"
                , null, null, "student_table");
            System.out.println("--teacher_table表和student_table之間"
                + "的外鍵約束--");
            printResultSet(rs);
            // 獲取student_table表的全部數據列
            rs = dbmd.getColumns(null, null, "student_table", "%");
            System.out.println("--student_table表的全部數據列--");
            printResultSet(rs);
        }
    }
    public void printResultSet(ResultSet rs)throws SQLException
    {
        ResultSetMetaData rsmd = rs.getMetaData();
        // 打印ResultSet的所有列標題
        for (int i = 0 ; i < rsmd.getColumnCount() ; i++ )
        {
            System.out.print(rsmd.getColumnName(i + 1) + "\t");
        }
        System.out.print("\n");
        // 打印ResultSet里的全部數據
        while (rs.next())
        {
            for (int i = 0; i < rsmd.getColumnCount() ; i++ )
            {
                System.out.print(rs.getString(i + 1) + "\t");
            }
            System.out.print("\n");
        }
        rs.close();
    }
    public static void main(String[] args)
        throws Exception
    {
        DatabaseMetaDataTest dt = new DatabaseMetaDataTest();
        dt.initParam("mysql.ini");
        dt.info();
    }
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM