Java Web系列:JDBC 基礎

来源:http://www.cnblogs.com/easygame/archive/2016/01/09/5116251.html
-Advertisement-
Play Games

ADO.NET在Java中的對應技術是JDBC,企業庫DataAccessApplicationBlock模塊在Java中的對應是spring-jdbc模塊,EntityFramework在Java中對應的ORM是Hibernate。關係資料庫、SQL、資料庫事務、分散式事務的概念都是通用的。1.J...


ADO.NET在Java中的對應技術是JDBC,企業庫DataAccessApplicationBlock模塊在Java中的對應是spring-jdbc模塊,EntityFramework在Java中對應的ORM是Hibernate。關係資料庫、SQL、資料庫事務、分散式事務的概念都是通用的。

1.JDBC

JDBC代碼和ADO.NET代碼一樣,除了學習時寫demo來掌握核心對象外,不適合在項目中直接使用。另外Java中萬年不變的學術派抽象介面給我目前看到的大多數容器和框架帶來了極大的不便,如Tomcat和Spring中定義的一些抽象類型無論是屬性和方法都和.NET中的很相似,但又不得不和Java中的基礎介面適配。抽象不能像Java中一樣只關註操作介面而不關註基礎的數據結構,正確的類型的抽象比方法的抽象更重要,但Java中抽象的做法好像還有一個原則就是與眾不同,而不只是關註操作。

(1)核心對象

ADO.NET中的4個核心抽象類是DbConnectionDbCommandDbParameterDbTransaction.DataAdapter和DataSet構建在核心對象之上。

JDBC的4個核心介面DataSourceConnectionStatementResultSetPreparedStatement是Statement的子類型。

雖然兩者不能完全匹配,對資料庫操作的核心操作是一致的,都是打開鏈接、發送命令和關閉連接的過程。

(2)參數處理

 參數的核心是索引和參數值。ADO.NET中提供了DbDataParameter類型用於參數的抽象。JDBC中沒有提供參數的抽象類型,而是通過PreparedStatement定義的方法來設置參數,可以通過Connection對象獲取該類型對象。

(3)事務處理

事務的核心操作是提交和回滾。ADO.NET中提供了DbTransaction類型用於事務的抽象,可以通過DbConnection的BeginTransaction方法開啟顯式事務.JDBC中沒有提供事務的抽象類型,而是通過Connection定義的setAutoCommitcommitrollback方法來操作事務。隱性事務的自動提交和顯性事務的手動控制方面兩者是一致的。

(4)數據源

JDBC中的Connection不具備連接池等高級功能。DataSource定義了數據源介面,用於連接管理、連接池和分散式事務等高級功能,連接池的重要性不用強調了。我們可以使用Apache Commons DBCP 2或C3P0(Hibernate)等第三方DataSource實現,Spring框架也有內置的一些簡單的DataSource實現,如SimpleDriverDataSource、SingleConnectionDataSource、DriverManagerDataSource等。

我們分別使用DriverManager、commons-dbcp2(參考1)、c3p0(參考2)和h2database(參考3)演示無連接池、dbcp2連接池、c3p0連接池的使用:

 1 package test.jdbc;
 2 
 3 import java.beans.PropertyVetoException;
 4 import java.sql.Connection;
 5 import java.sql.DriverManager;
 6 import java.sql.PreparedStatement;
 7 import java.sql.ResultSet;
 8 import java.sql.SQLException;
 9 import javax.sql.DataSource;
10 
11 import org.apache.commons.dbcp2.BasicDataSource;
12 import com.mchange.v2.c3p0.ComboPooledDataSource;
13 
14 public class Jdbc {
15     public static void main(String[] args) throws ClassNotFoundException, SQLException, PropertyVetoException {
16         String ddl = "create table user(id integer not null primary key,username varchar(64))";
17         String dml = "insert into user (id,username) values(1,'tom')";
18         String query = "select id,username from user where username=?";
19         String className = "org.h2.Driver";
20         String url = "jdbc:h2:mem:test";
21         // Connection conn = DriverManager.getConnection(url);
22         Connection conn = get_dbcp2_dataSource(className, url).getConnection();
23         // Connection conn = get_c3p0_dataSource(className,//
24         // url).getConnection();
25         conn.setAutoCommit(false);
26         conn.prepareStatement(ddl).execute();
27         conn.createStatement().execute(dml);
28         conn.commit();
29         conn.setAutoCommit(true);
30         PreparedStatement statement = conn.prepareStatement(query);
31         statement.setString(1, "tom");
32         ResultSet rs = statement.executeQuery();
33         User user = new User();
34         while (rs.next()) {
35             user.setId(rs.getInt(1));
36             user.setUsername("username");
37             break;
38         }
39         conn.close();
40         System.out.println(String.format("id:%d,username:%s", user.getId(), user.getUsername()));
41     }
42 
43     public static Connection getConnection(String driverClassName, String url) {
44         try {
45             Class.forName(driverClassName);
46         } catch (ClassNotFoundException e1) {
47             e1.printStackTrace();
48         }
49         Connection conn = null;
50         try {
51             conn = DriverManager.getConnection(url);
52         } catch (SQLException e) {
53             e.printStackTrace();
54         }
55         return conn;
56     }
57 
58     public static DataSource get_dbcp2_dataSource(String clssName, String url) {
59 
60         BasicDataSource dataSource = new BasicDataSource();
61         dataSource.setDriverClassName(clssName);
62         dataSource.setUrl(url);
63         return dataSource;
64     }
65 
66     public static DataSource get_c3p0_dataSource(String clssName, String url) throws PropertyVetoException {
67 
68         ComboPooledDataSource dataSource = new ComboPooledDataSource();
69         dataSource.setDriverClass(clssName);
70         dataSource.setJdbcUrl(url);
71         return dataSource;
72     }
73 }

 

其中2dbcp、c3p0和h2database的Maven依賴如下:

 1         <dependency>
 2             <groupId>com.h2database</groupId>
 3             <artifactId>h2</artifactId>
 4             <version>1.4.190</version>
 5         </dependency>
 6         <dependency>
 7             <groupId>org.apache.commons</groupId>
 8             <artifactId>commons-dbcp2</artifactId>
 9             <version>2.1.1</version>
10         </dependency>
11         <dependency>
12             <groupId>com.mchange</groupId>
13             <artifactId>c3p0</artifactId>
14             <version>0.9.5.2</version>
15         </dependency>

2.Spring Jdbc

JDBC和ADO.NET的API類似,都不適合我們直接使用,如果不適用ORM框架,在.NET中我們使用DataAccessApplicationBlock,在Java中我們可以使用Spring JDBC。Spring JDBC的核心類是JdbcTemplate

(1)Sprnig的委托實現

要使用Spring Jdbc的功能,首先要理解Spring中委托的使用方式,Spring定義一個包含該委托簽名的介面(這些介面通常都是沒有內置實現的),當需要委托參數時,使用該介面作為參數類型,利用Java中的匿名類功能,可以在內聯代碼中實現介面定義的委托,下麵列舉幾個常見的委托介面:

Func<Connection,PreparedStatement>:PreparedStatement介面的createPreparedStatement方法。

1 public interface PreparedStatementCreator {
2 
3     PreparedStatement createPreparedStatement(Connection con) throws SQLException;
4 
5 }

Func<PreparedStatement,T>:PreparedStatementCallback泛型介面的doInPreparedStatement方法。

1 public interface PreparedStatementCallback<T> {
2 
3     T doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException;
4 
5 }

Func<TransactionStatus,T>:TransactionCallback泛型介面的T doInTransaction(TransactionStatus status)方法。

1 public interface TransactionCallback<T> {
2 
3     T doInTransaction(TransactionStatus status);
4 
5 }

Fcun<ResultSet,T>:ResultSetExtractor泛型方法的T extractData(ResultSet rs)方法。

1 public interface ResultSetExtractor<T> {
2 
3     T extractData(ResultSet rs) throws SQLException, DataAccessException;
4 
5 }

(1)JdbcTemplate

 JdbcTemplate需要配合DataSource一起使用。JdbcTemplate的代碼中很多都是通過IDE自動生成匿名類導致的,真正手寫的代碼量並不多。

 1     public static void main(String[] args) throws ClassNotFoundException, SQLException, PropertyVetoException {
 2         String ddl = "create table user(id integer not null primary key,username varchar(64))";
 3         String dml = "insert into user (id,username) values(1,'tom')";
 4         String query = "select id,username from user where username=?";
 5         String className = "org.h2.Driver";
 6         String url = "jdbc:h2:mem:test";
 7 
 8         DataSource dataSource = get_dbcp2_dataSource(className, url);
 9         JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
10         PlatformTransactionManager tm = new DataSourceTransactionManager(dataSource);
11         TransactionTemplate tt = new TransactionTemplate(tm);
12         tt.execute(new TransactionCallback() {
13 
14             @Override
15             public Object doInTransaction(TransactionStatus status) {
16                 jdbcTemplate.execute(ddl);
17                 jdbcTemplate.execute(dml);
18                 return status;
19             }
20         });
21 
22         User user = jdbcTemplate.query(query, new Object[] { "tom" }, new ResultSetExtractor<User>() {
23             @Override
24             public User extractData(ResultSet rs) throws SQLException, DataAccessException {
25                 User user = new User();
26                 while (rs.next()) {
27                     user.setId(rs.getInt(1));
28                     user.setUsername(rs.getString("username"));
29                     break;
30                 }
31                 return user;
32             }
33         });
34         System.out.println(String.format("id:%d,username:%s", user.getId(), user.getUsername()));
35     }

(3)TransactionTemplate

在上面的代碼中出現了TransactionTemplate用於事務處理,TransactionTemplate依賴PlatformTransactionManager,Spring Jdbc中定義的DataSourceTransactionManager實現類用於處理資料庫事務。在Spring的orm、jsm、tx等模塊中還有其他的實現。

(4)JdbcDaoSupport

JdbcDaoSupport是一個在內部使用JdbcTemplate欄位並且實現了DaoSupport介面的抽象類,可供我們自定義DAO類時參考或用作基類。

 1 class MyDao extends JdbcDaoSupport {
 2     public MyDao(DataSource dataSource) {
 3         this.setJdbcTemplate(new JdbcTemplate(dataSource));
 4     }
 5 
 6     @SuppressWarnings("unchecked")
 7     public void init(String ddl, String dml) {
 8         PlatformTransactionManager tm = new DataSourceTransactionManager(this.getDataSource());
 9         TransactionTemplate tt = new TransactionTemplate(tm);
10 
11         tt.execute(new TransactionCallback() {
12 
13             @Override
14             public Object doInTransaction(TransactionStatus status) {
15                 getJdbcTemplate().execute(ddl);
16                 getJdbcTemplate().execute(dml);
17                 return status;
18             }
19         });
20     }
21 
22     public User getUser(String query, String username) {
23         return this.getJdbcTemplate().query(query, new Object[] { username }, new ResultSetExtractor<User>() {
24             @Override
25             public User extractData(ResultSet rs) throws SQLException, DataAccessException {
26                 User user = new User();
27                 while (rs.next()) {
28                     user.setId(rs.getInt(1));
29                     user.setUsername(rs.getString("username"));
30                     break;
31                 }
32                 return user;
33             }
34         });
35     }
36 }

參考

(1)http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi

(2)http://sourceforge.net/projects/c3p0/

(3)http://www.h2database.com/html/cheatSheet.html

(4)http://commons.apache.org/proper/commons-dbcp/guide/jndi-howto.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目:Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = "aabcc",s2 = "dbbca",When s3 = "aadbbcbcac", r...
  • 這一系列文章目的不是講ruby,也不是講selenium-webdriver,而是通過一個登錄soso首頁的小例子講怎樣一步一步寫好自動化測試。目標是:面向對象編程,實現邏輯與數據分離。如果你覺得已經學會了selenium-webdriver這個工具,而且也可以自己寫一些小例子,但是似乎又是在雲里霧...
  • 一、簡介 在一些web、email、database等應用里,比如彩鈴,我們的應用在任何時候都要準備應對數目巨大的連接請求,同時,這些請求所要完成的任務卻又可能非常的簡單,即只占用很少的處理時間。這時,我們的應用有可能處於不停的創建線程並銷毀線程的狀態。雖說比起進程的創建,線程的創建時間已經大大縮短...
  • 題目:Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For example,Given n = 3, your program should return ...
  • NSDate#import int main(int argc, const char * argv[]) { @autoreleasepool { //通過date方法創建的時間對象,對象就保存了當前的時間; /* NSDate *now=[NSDate date]...
  • Object作為對象中的上帝,我們時刻關註著上帝中的行為。但是上帝之手有時候還不太好用,所以我們有時候要進行覆寫。public String toString(){ //code}public boolean equals(Object obj){ // obj 強轉 // 比較...
  • 1.準備工作 (1)PHP 版本5.6.17 下載地址 PHP官網 (2)Nginx 版本1.8.0 下載地址 Nginx官網 (3)MySQL 版本5.7.10MySQL官網2.php的安裝與配置 直接解壓下載好的php包,到D盤wnmp目錄(D:\wnmp),這裡把解壓出來的文件夾重命名...
  • /*** 導入文件Action;*/private File excelFile;// 保存原始文件名private String excelFileFileName;// 保存原始文件名private String importResult;// 將Excel文件解析完畢後信息存放到這個User對...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...