日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java】14 JDBC编程学习总结

發布時間:2025/3/20 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java】14 JDBC编程学习总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

        • 一、JDBC是什么?
        • 二、為什么要使用JDBC?
        • 三、DDL、DML、DCL分別代表什么
        • 四、JDBC有三個操作步驟
          • 實例代碼
          • 實例代碼
          • 實例代碼
        • 五、使用PreparedStatement執行SQL語句
          • 實例代碼
        • 六、使用CallableStatement調用存儲過程
          • 實例代碼
        • 七、可滾動、可更新結果集
          • 實例代碼
        • 八、處理Bob類型的數據
        • 九、 Java7新增的RowSetFactory與RowSet
          • 實例代碼
        • 十、離線RowSet
          • 實例代碼
        • 十一、離線RowSet的分頁查詢
          • 實例代碼
        • 十二、事務處理
          • 實例代碼
        • 十三、使用DatabaseMetaData分析數據庫信息
          • 實例代碼
        • 十四、使用連接池管理連接
          • 實例代碼1
          • 實例代碼2

一、JDBC是什么?

JDBC-Java Database Connectivity-Java數據庫連接

二、為什么要使用JDBC?

可以使用相同的API實現連接、操作不同的數據庫

三、DDL、DML、DCL分別代表什么

DDL(Data Definition Language 數據定義語言)語句:主要由create,alter,drop和truncate四個關鍵字完成
DML(Data Manipulation Language 數據操作語言)語句:主要由insert,update和delete三個關鍵字完成
DCL(Data Control Language 數據控制語言) 語句:主要由grant和revoke兩個關鍵字組成
事務性語言:主要由commit,rollback和savepoint三個關鍵字組成

四、JDBC有三個操作步驟

建立與數據庫的連接、執行SQL語句、獲得SQL語句執行結果

  • 加載驅動,規范
    Class.forName(dirver)
  • 使用Connection創建Connection對象,以便可以使用Connection創建Statement對象
    Connection conn = DriverManager.getConnection(url,user,pass)
  • 使用Connection對象創建Statement對象,以便使用Statement對象的executeXxx方法
    Statement stmt = conn.createStatement()
  • 調用Statement對象的executeUpdate()、executeQuery()、execute()方法
  • executeUpdate():用于執行DML語句,返回一個整數

    實例代碼
    /** * @ClassName: ExecutionDDLTest* @description: 本節代碼主要實現使用executeLargeUpdate()來執行DDL語句* DDL語言:主要由create,drop,alter,truncate* @author: FFIDEAL* @Date: 2020年4月5日 下午9:28:59*/ package M13;import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.util.Properties;import com.mysql.cj.jdbc.Driver;public class ExecutionDDLTest {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來創建一個Statement對象Statement stmt = conn.createStatement()){//執行DDL語句,創建數據表stmt.executeUpdate(sql);}}public static void main(String[] args) throws Exception{ExecutionDDLTest ed = new ExecutionDDLTest();ed.initParam("E:\\JavaCode\\Code\\src\\M13\\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("=======表創建完成======");} }

    executeQuery():執行select語句,查詢到的結果

    實例代碼
    /** * @ClassName: ConnMySql* @description: 本節代碼簡單示范了JDBC編程,并通過ResultSet獲得結果集的過程* @author: FFIDEAL* @Date: 2020年4月4日 下午8:22:06*/package M13;import java.security.interfaces.RSAKey; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement;public class ConnMySql {public static void main(String[] args) throws Exception{//1.加載驅動,使用反射知識,現在就記住/* 5版本是Class.forName("com.mysql.jdbc.Driver");* 8版本是Class.forName("com.mysql.cj.jdbc.Driver");*/Class.forName("com.mysql.cj.jdbc.Driver");try (/*2.使用DriverManager獲取數據庫連接* 其中返回的Connection就代表了Java程序和數據庫的連接* 不同數據庫URL寫法需要查驅動文檔,用戶名、密碼有DBA分配*/Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/crazyjavajdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC", "root","root");//3.使用Connection來創建一個Statement對象Statement stmt = conn.createStatement();/*4.執行SQL語句* Statement有三種執行SQL語句的方法:* ①.execute()可執行任何SQL語句-返回一個boolean值,如果執行后第一個結果是ResultSet就返回true,否則返回false* ②.executeQuery()執行select語句 - 返回查詢到的結果集* ③.executeUpdate()用于執行DML語句-返回一個整數,代表被SQL語句影響的記錄條數*/ // ResultSet rs = stmt.executeQuery("select s.* , teacher_name from student_table s,teacher_table t where s.java_teacher = t.teacher_id")ResultSet rs = stmt.executeQuery("select s.* , t.teacher_name "+ "from student_table s , teacher_table t "+ "where s.java_teacher = t.teacher_id")){/*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));}}} }

    execute():可以執行任何一個SQL語句,返回一個boolean
    但是可以執行getResultSet():獲得該Statement執行查詢語句所返回的ResultSet對象
    getUpdateCount():獲取該Statement執行的DML語句所影響的記錄條數

    實例代碼
    /** * @ClassName: ExecuteSQL* @description: 本機代碼主要討論使用execute()方法來執行SQL語句* execute()方法的有點:幾乎可以執行任何的SQL語句,而不用考慮DML(executeUpdate)還是DDL()* execute():可以執行任何一個SQL語句,返回一個boolean,* 但是可以執行* getResultSet():獲得該Statement執行查詢語句所返回的ResultSet對象* getUpdateCount():獲取該Statement執行的DML語句所影響的記錄條數 * @author: FFIDEAL* @Date: 2020年4月6日 下午2:30:58*/ package M13;import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties;public class ExecuteSQL {private String driver;private String url;private String user;private String pass;public void initParam(String paramFile) throws Exception{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);Statement stmt = conn.createStatement();){//執行SQL語句,返回boolean值表示是否包含ResultSetboolean hasResultSet = stmt.execute(sql);if(hasResultSet) {try(//獲取結果集ResultSet rs = stmt.getResultSet();){//ResultSetMetaData是用于分析結果集合的元數據接口java.sql.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.println("\n");}}}}}public static void main(String[] args) throws Exception {ExecuteSQL es = new ExecuteSQL();es.initParam("E:\\JavaCode\\Code\\src\\M13\\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");es.executeSQL("insert into my_test values(3,'小紅');");System.out.println("=====執行查詢數據的查詢語句=====");es.executeSQL("select * from my_test");} }

    五、使用PreparedStatement執行SQL語句

    PreparedStatement接口可以允許在SQL中使用占位符(?),這是在Statement接口中中不被允許的。

    PreparedStatement的效率比Statement高,這是因為可以使用PreparedStatement對象多次高效的執行SQL語句。使用辦法和Statement方法類似,且提供的方法也是類似的,有execute()方法、executeUpdate()方法和executeQuery()方法等

    除了效率較高以外,PreparedStatement還有一個優勢,就是使用PreparedStatement不需要拼接SQL語句,見一下代碼的兩個方法中的SQL語句。

    除了上述兩個優點以外,使用PreparedStatement可以防止SQL注入(常見的利用SQL語句漏洞來入侵的方法)

    PreparedStatement ps = conn.preparedStatement("insert into student_table values(null,?,1)");
    實例代碼
    /** * @ClassName: PreparedStatementTest* @description: 本節代碼主要討論PreparedStatement和Statement性能的對比* @author: FFIDEAL* @Date: 2020年4月6日 下午6:01:24*/ package M13;import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.Statement; import java.util.Properties;public class PreparedStatementTest {private String driver;private String url;private String user;private String pass;public void initParam(String paramFile) throws Exception{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);Statement stmt = conn.createStatement();){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 insertUsePreparedStatement() throws Exception{long start = System.currentTimeMillis();try(Connection conn = DriverManager.getConnection(url, user, pass);PreparedStatement ps = conn.prepareStatement("insert into student_table values(null,1,?)");){//100次為PreparedStatement的參數設置,可以插入100條記錄for (int i = 0; i < 100; i++) {ps.setString(1, "姓名" + i);ps.setInt(1, i);ps.executeUpdate();}System.out.println("使用PreparedStatement費時:"+ (System.currentTimeMillis() - start));}}//使用execute()方法來輸出查詢結果public void selectAll() throws Exception{try(Connection conn = DriverManager.getConnection(url, user, pass);Statement stmt = conn.createStatement();){boolean hasResultSet = stmt.execute("select * from student_table");if(hasResultSet) {try(//通過getResultSet方法獲得結果集ResultSet rs = stmt.getResultSet();){//獲得變化的數字ResultSetMetaData rsmd = rs.getMetaData();int col = rsmd.getColumnCount();while(rs.next()) {for (int i = 0; i < col; i++) {System.out.print(rs.getString(i + 1) + "\t");}System.out.println("\n");}}}}}public static void main(String[] args) throws Exception{PreparedStatementTest pst = new PreparedStatementTest();pst.initParam("E:\\JavaCode\\Code\\src\\M13\\mysql.ini");pst.insertUseStatement();pst.insertUsePreparedStatement();pst.selectAll();} }

    六、使用CallableStatement調用存儲過程

    前提是要在數據庫里有這個事務

    //使用Connection來創建一個CallableStatement對象 cstmt = conn.prepareCall("{call add_pro(?,?,?)}"); //傳入參數可以用setXxx(index, number); //使用registerOutParameter()方法來注冊參數 //之后用execute()來執行 //getXxx(int index)來獲得參數
    實例代碼
    /** * @ClassName: CallableStatemnetTest* @description: 本節代碼主要討論CallableStatement調用存儲過程* @author: FFIDEAL* @Date: 2020年4月6日 下午8:51:05*/ package M13;import java.io.FileInputStream; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Types; import java.util.Properties;public class CallableStatemnetTest {private String driver;private String url;private String user;private String pass;public void initParam(String paramFile) throws Exception{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 CallProcedure() throws Exception{try(Connection conn = DriverManager.getConnection(url, user, pass);//通過Connection對象創建一個CallableStatement對象,"{call 存儲過程名稱(占位符參數1,占位符參數2,……)}"CallableStatement cs = conn.prepareCall("{call add_pro(?,?,?)}");){cs.setInt(1, 2);cs.setInt(2, 3);//輸出int類型cs.registerOutParameter(3, Types.INTEGER);//執行程序cs.execute();//輸出結果System.out.println("執行結果是:" + cs.getInt(3));}}public static void main(String[] args) throws Exception {CallableStatemnetTest cst = new CallableStatemnetTest();cst.initParam("E:\\JavaCode\\Code\\src\\M13\\mysql.ini");cst.CallProcedure();} }

    七、可滾動、可更新結果集

    ResultSet除了next()指針外,還可以使用absolute()、previous()、afterLast()等方法自由移動記錄指針

    在使用Connection創建了Statement或者PreparedStatement是還額外傳入如下兩個參數

  • resultSetType:控制ResultSet的類型,可以是以下三個值

    • ResultSet.TYPE_FORWARD_ONLY:該常量記錄指針只能向前移動
    • ResultSet.TYPE_SCROLL_INSENSITIVE:該常量控制記錄指針可以自動移動(可滾動結果集),但是底層數據的改變不會影響ResultSet的內容變化
    • ResultSet.TYPE_SCROLL_SENSITIVE:該常量控制記錄指針可以自動移動(可滾動結果集),但是底層數據的改變會影響ResultSet的內容變化
  • ResultSetConcurrent:控制ResultSet的并發類型,該參數可以接收如下兩個值

    • ResultSet.CONCUR_READ_ONLY:該常量表示ResultSet是只讀的并發模式(默認)
    • ResultSet.CONCUR_UPDATABLE:該常量表示ResultSet是可更新的并發模式

    下面代碼通過這兩個參數創建一個PreparedStatement對象,有該對象生成的ResultSet對象將是可滾動的、可更新的

  • //使用Connection創建一個PreparedStatement對象 //傳入控制結果集可滾動、可更新的參數 ps = conn.preparedStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,SesultSet.CONCUR_UPDATABLE);
    實例代碼
    /** * @ClassName: ResultSetTest* @description: 本段代碼主要討論通過Connection來創建PreparedStatement對象,并通過這一對象來是數據庫達到可滾動可更新的目的* @author: FFIDEAL* @Date: 2020年4月6日 下午11:18:39*/ package M13;import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Properties;public class ResultSetTest {private String driver;private String url;private String user;private String pass;public void initParam(String paramFile) throws Exception{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 query(String sql) throws Exception{try(Connection conn = DriverManager.getConnection(url, user, pass);PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);ResultSet rs = ps.executeQuery();){rs.last();//獲得行數int rowCount = rs.getRow();System.out.println("共有" + rowCount + "行");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 rst = new ResultSetTest();rst.initParam("E:\\JavaCode\\Code\\src\\M13\\mysql.ini");rst.query("select * from student_table");} }

    八、處理Bob類型的數據

    Bob(Binary Long Object)是二進制長對象的意思,Blob列通常用于存儲大文件,典型的Blob內容是一張圖片或者一個聲音文件,由于它的特殊性,必須使用特殊的方法來存儲。而Blob列可以吧圖片、聲音等文件轉化為二進制數據保存在數據庫里,并可以從數據庫中恢復指定文件。

    Blob數據插入數據庫需要使用PreparedStatement,該對象有一個方法:setBinaryStream()

    九、 Java7新增的RowSetFactory與RowSet

    RowSet繼承自ResultSet接口,RowSet接口下包含JdbcRowSet、CacheRowSet、FilteredRowSet、JoinRowSet和WebRowSet常用子接口。除了JdbcRowSet需要與數據庫保持連接以外,其他的子接口都是離線的RowSet,但是并不好用(僅做了解)——可滾動、客休該的特性

    Java新增的RowSetFactory接口和RowSetProvider類,其中RowSetProvider負責創建RowSetFactory,而RowSetFactory則提供了以下方法創建RowSet實例

    • CachedRowSet createCachedRowSet():創建一個默認的CachedRowSet
    • FilteredRowSet createFilteredRowSet():創建一個默認的FilteredRowSet
    • JdbcRowSet createJdbcRowSet():創建一個默認的JdbcRowSet
    • JoinRowSet createJoinRowSet():創建一個默認的JoinRowSet
    • WebRowSet createWebRowSet():創建一個默認的WebRowSet
    實例代碼
    /** * @ClassName: JdbcRowSetTest* @description: 本節代碼主要討論通過JdbcRowSetImpl示范了使用JdbcRowSet的可滾動、可修改特性* @author: FFIDEAL* @Date: 2020年4月7日 下午4:34:09*/ package M13;import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties;import javax.sql.rowset.JdbcRowSet; import javax.sql.rowset.RowSetFactory; import javax.sql.rowset.RowSetProvider;public class JdbcRowSetTest {private String driver;private String url;private String user;private String pass;public void initParam(String paramFile) throws Exception{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 update(String sql) throws Exception{//使用RowSetProvider創建RowSetFactoryRowSetFactory rsf = RowSetProvider.newFactory();try(//使用RowSetFactory創建默認的JdbcRowSet實例JdbcRowSet jrs = rsf.createJdbcRowSet()){//設置必要的連接信息jrs.setUrl(url);jrs.setUsername(user);jrs.setPassword(pass);//設置查詢語句jrs.setCommand(sql);//執行查詢jrs.execute();jrs.afterLast();//將前滾動結果集while(jrs.previous()) {System.out.println("===1====");System.out.println(jrs.getString(1)+ "\t" + jrs.getString(2)+ "\t" + jrs.getString(3)+ "\t" + jrs.getInt("student_id"));if(jrs.getInt("student_id") == 3) {//修改制定記錄行jrs.updateString("student_name","Java");System.out.println("===2====");jrs.updateRow();}}}}public static void main(String[] args) throws Exception{JdbcRowSetTest jrst = new JdbcRowSetTest();jrst.initParam("E:\\JavaCode\\Code\\src\\M13\\mysql.ini");jrst.update("select s.* from student_table s");} }

    十、離線RowSet

    使用離線RowSet可以將底層數據庫數據讀入內存,封裝成RowSet對象,該對象不僅安全,編程還比較簡單。

    實例代碼
    /** * @ClassName: CachedRowSetTest* @description: 本節代碼討論用CachedRowSet來處理讀取數據* @author: FFIDEAL* @Date: 2020年4月7日 下午6:14:27*/ package M13;import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties;import javax.sql.rowset.CachedRowSet; import javax.sql.rowset.RowSetFactory; import javax.sql.rowset.RowSetProvider;public class CachedRowSetTest {private String driver;private static String url;private static String user;private static String pass;public void initParam(String paramFile) throws Exception{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 CachedRowSet query(String sql) throws Exception{Connection conn = DriverManager.getConnection(url, user, pass);Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql);//使用RowSetProvider創建RowSetFactoryRowSetFactory factory = RowSetProvider.newFactory();//創建默認的CachedRowSet實例CachedRowSet cachers = factory.createCachedRowSet();//使用ResultSet裝填RowSet,調用了RowSet的populate(ResultSet rs)方法來包裝給定的ResultSet //接下來就關閉了ResultSet、Statement、Connection等數據庫資源cachers.populate(rs);//關閉資源rs.close();stmt.close();conn.close();return cachers;}public static void main(String[] args) throws Exception{CachedRowSetTest ct = new CachedRowSetTest();ct.initParam("E:\\JavaCode\\Code\\src\\M13\\mysql.ini");CachedRowSet rs = ct.query("select * from student_table");rs.afterLast();//向前滾動結果集while(rs.previous()) {System.out.println(rs.getString(1)+ "\t" + rs.getString(2)+ "\t" + rs.getString(3));if(rs.getInt("student_id") == 3) {//修改制定記錄行rs.updateString("student_name","Java");rs.updateRow();}}//重新獲取數據庫連接Connection conn = DriverManager.getConnection(url, user, pass);conn.setAutoCommit(false);//把對RowSet所做的修改同步到底底層數據庫rs.acceptChanges(conn);} }

    十一、離線RowSet的分頁查詢

    若一次性將數據加載到內存中,就會造成內存資源緊張的問題,因此在CachedRowSet提供了分頁的功能

    CachedRowSet通過以下方法控制分頁

    • populate(ResultSet rs, int satrtRow):使用給定的ResultSet裝填RowSet,從ResultSet的第startRow條記錄開始填裝
    • setPageSize(int PageSize):設置CachedRowSet每次返回多少條記錄
    • previousPage():在底層ResultSet可用的情況下,讓CachedRowSet讀取上一頁記錄
    • nextPage():在底層ResultSet可用的情況下,讓CachedRowSet讀取下一頁記錄
    實例代碼
    /** * @ClassName: CachedRowSetPage* @description: 本節代碼主要討論RowSet的查詢分頁的問題* @author: FFIDEAL* @Date: 2020年4月7日 下午8:02:59*/ package M13;import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties;import javax.sql.rowset.CachedRowSet; import javax.sql.rowset.RowSetFactory; import javax.sql.rowset.RowSetProvider;public class CachedRowSetPage {private String driver;private static String url;private static String user;private static String pass;public void initParam(String paramFile) throws Exception{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 CachedRowSet query(String sql, int pageSize, int page) throws Exception{try(Connection conn = DriverManager.getConnection(url, user, pass);Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql);){//要通過RowSetprovider創建RowSetFactoryRowSetFactory factory = RowSetProvider.newFactory();//通過RowSetFactory創建默認的CachedRowSetCachedRowSet cachedRs = factory.createCachedRowSet();//顯示每頁顯示的pagesize條記錄cachedRs.setPageSize(10);//使用ResultSet裝填RowSet,設置從第幾條記錄開始cachedRs.populate(rs, (page - 1) * pageSize + 1);return cachedRs;}}public static void main(String[] args) throws Exception{CachedRowSetPage cachedRsp = new CachedRowSetPage();cachedRsp.initParam("E:\\JavaCode\\Code\\src\\M13\\mysql.ini");//顯示要看第十頁的記錄,每頁顯示10行CachedRowSet rs = cachedRsp.query("select * from student_table", 10, 10);//向后滾動while(rs.next()) {System.out.println(rs.getString(1)+ "\t" + rs.getString(2)+ "\t" + rs.getString(3));}} }

    十二、事務處理

    事務具備四個特性(ACID):分別為原子性、一致性、隔離性、持續性

    數據庫事務由以下語句組成:

    • 一組DML,經過這組DML語句修改之后數據保持較好的一致性
    • 一條DDL語句
    • 一條DCL語句

    提交事務:顯示提交(commit);自動提交(執行DDL或者DCL語句,或者程序正常退出)

    事務遇到執行失敗會如何——回滾:顯式回滾(rollback);自動回滾(系統錯誤或者強行退出)

    #歷史開始事務 begin #向student_table表中插入3條數據 insert into jdbc_test values(null,'xx',1); insert into jdbc_test values(null,'yy',1); insert into jdbc_test values(null,'zz',1); #查詢student_table表的記錄 select * from jdbc_test; #回滾事務① rollback; #再次查詢② select * from jdbc_test;

    以上代碼在①處發現插入的三條記錄看不到了(隔離性),執行②時看到的是剛插入時候的樣子

    在JDBC中可以調用Connection的setAutoCommit()方法來關閉自動提交,開啟事務;同時可以通過Connection中 getAutoCommit()方法來返回該鏈接的自動提交模式

    //關閉自動提交,開啟事務 conn.setAutoCommit(false);

    一旦事務創建完畢,就像平時創建Statement對象,然后執行任意多條語句

    stmt.executeUpdate(...); stmt.executeUpdate(...); stmt.executeUpdate(...);

    以上代碼只是被執行但是沒有生效,最后要調用Connection中的commit()來提交

    conn.commit(); //提交事務

    如果任意一條語句失敗,就要調用Connection中的rollback()來回滾

    //回滾事務 conn.rollback();
    實例代碼
    /** * @ClassName: TranscationTest* @description: 本節代碼討論了當程序出現了SQLException錯誤時,系統將回滾事務* @author: FFIDEAL* @Date: 2020年4月7日 下午10:17:59*/ package M13;import java.io.FileInputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.util.Properties;public class TranscationTest {private String driver;private static String url;private static String user;private static String pass;public void initParam(String paramFile) throws Exception{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 insetInTransaction(String[] sqls) throws Exception{try(Connection conn = DriverManager.getConnection(url, user, pass);){//關閉自動提交,開啟事務conn.setAutoCommit(false);try(//使用Connection來創建一個Statement對象Statement stmt = conn.createStatement();){//循環多次執行SQL語句for(String sql:sqls) {stmt.executeUpdate(sql);}}conn.commit();}}public static void main(String[] args) throws Exception{TranscationTest tt = new TranscationTest();tt.initParam("E:\\JavaCode\\Code\\src\\M13\\mysql.ini");String[] sqls = new String[] {"insert into jdbc_test values(null,'xx',1);","insert into jdbc_test values(null,'yy',1);","insert into jdbc_test values(null,'zz',1);","insert into jdbc_test values(null,'ccc',5)"};tt.insetInTransaction(sqls);System.out.println("==");} }

    十三、使用DatabaseMetaData分析數據庫信息

    JDBC提供了DatabaseMetaData來封裝數據庫信息,通過Connection提供的getMetaData()就可以獲取數據庫對應的DatabaseMetaData對象

    實例代碼
    /** * @ClassName: DatabaseMetaDataTest* @description: 本節代碼主要討論通過DatabaseMetaData分析當前Connection連接對應數據庫的一些基本信息,* 包括當前數據庫包含多少數據表,存儲過程,student_table表的數據列、主鍵、外鍵等信息* @author: FFIDEAL* @Date: 2020年4月7日 下午11:05:41*/ package M13;import java.io.FileInputStream; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties;import com.mysql.cj.jdbc.result.ResultSetMetaData;public class DatabaseMetaDataTest {private String driver;private static String url;private static String user;private static String pass;public void initParam(String paramFile) throws Exception{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 info() throws Exception{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, "student_table", null, null, "teacher_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);}}/*** @param rs*/private void printResultSet(ResultSet rs) throws SQLException{// TODO Auto-generated method stubjava.sql.ResultSetMetaData rsmd = rs.getMetaData();//打印ResultSet所有的列標題for (int i = 0; i < rsmd.getColumnCount(); i++) {System.out.print(rsmd.getColumnName(i + 1) + "\t");}System.out.println("");//打印ResultSet所有的數據while(rs.next()) {for (int i = 0; i < rsmd.getColumnCount(); i++) {System.out.print(rs.getString(i + 1) + "\t");}System.out.println("");}rs.close();}public static void main(String[] args) throws Exception{DatabaseMetaDataTest dmdt = new DatabaseMetaDataTest();dmdt.initParam("E:\\JavaCode\\Code\\src\\M13\\mysql.ini");dmdt.info();} }

    十四、使用連接池管理連接

    數據庫連接池是Connection對象工廠。數據庫連接池的主要參數有:

    • 數據庫的初始連接數
    • 連接池的最大連接數
    • 連接池的最小連接數
    • 連接池每次增加的容量
    實例代碼1
    //以下代碼示范了Tomcat使用DBCP獲取數據庫的方式 //創建數據源對象 BasicDataSource ds = new BasicDataSource(); //設置連接池所需的驅動 ds.setDriverClassName("com.mysql.jc.jdbc.Driver"); //設置連接數據庫的URL ds.setUrl("jdbc:mysql://127.0.0.1:3306/crazyjavajdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"); //設置連接池數據庫的用戶名 ds.setUsername("root"); //設置連接數據庫的密碼 ds.setPassword("root"); //設置連接池的初始連接數 ds.setInitialSize(5); //設置連接池最多可有多少個活動連接數 ds.setMaxActive(20); //設置連接池中最小有2個空閑的連接 ds.setMinIdle(2); //所依賴的jar包:commons-dbcp.jar/commons-pool.jar //通過數據源獲取數據庫連接誒 Connection conn = ds.getConnection(); //釋放數據庫連接 conn.close();
    實例代碼2
    //以下代碼示范了C3P0連接數據庫的方式 //創建數據源對象 ComboPooledDataSource ds = new ComboPooledDataSource(); //設置連接池所需的驅動 ds.setDriverClass("com.mysql.jc.jdbc.Driver"); //設置連接數據庫的URL ds.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/crazyjavajdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"); //設置連接池數據庫的用戶名 ds.setUser("root"); //設置連接數據庫的密碼 ds.setPassword("root"); //設置連接池的初始連接數 ds.setInitialPoolSize(5); //設置連接池最多可有多少個活動連接數 ds.setMaxPoolSize(20); //設置連接池中最小有2個空閑的連接 ds.setMinPoolSize(2); //所依賴的jar包:c3p0-0.9.1.2.jar //通過數據源獲取數據庫連接誒 Connection conn = ds.getConnection(); //釋放數據庫連接 conn.close();

    總結

    以上是生活随笔為你收集整理的【Java】14 JDBC编程学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。