數據持久化
持久化(persistence):
- 把數據保存到可掉電式存儲設備中以供之后使用。大多數情況下,特別是企業級應用,數據持久化意味着將內存中的數據保存到硬盤上加以”固化”,而持久化的實現過程大多通過各種關系數據庫來完成。
- 持久化的主要應用是將內存中的數據存儲在關系型數據庫中,當然也可以存儲在磁盤文件、XML數據文件中。
Java 中的數據存儲技術
在Java中,數據庫存取技術可分為如下幾類:
- JDBC直接訪問數據庫
- JDO技術 第三方O/R工具,如Hibernate, ibatis 等
JDBC是java訪問數據庫的基石,JDO, Hibernate等只是更好的封裝了JDBC。
JDBC基礎
JDBC(Java Database Connectivity)是一個獨立於特定數據庫管理系統、通用的SQL數據庫存取和操作的公共接口(一組API),定義了用來訪問數據庫的標准Java類庫,使用這個類庫可以以一種標准的方法、方便地訪問數據庫資源
JDBC為訪問不同的數據庫提供了一種統一的途徑,為開發者屏蔽了一些細節問題。
JDBC的目標是使Java程序員使用JDBC可以連接任何提供了JDBC驅動程序的數據庫系統,這樣就使得程序員無需對特定的數據庫系統的特點有過多的了解,從而大大簡化和加快了開發過程。
JDBC體系結構
JDBC接口(API)包括兩個層次:
面向應用的API:Java API,抽象接口,供應用程序開發人員使用(連接數據庫,執行SQL語句,獲得結果)。
面向數據庫的API:Java Driver API,供開發商開發數據庫驅動程序用。
JDBC驅動程序分類
JDBC驅動程序:各個數據庫廠商根據JDBC的規范制作的 JDBC 實現類的類庫
JDBC驅動程序總共有四種類型:
第一類:JDBC-ODBC橋。
第二類:部分本地API部分Java的驅動程序。
第三類:JDBC網絡純Java驅動程序。
第四類:本地協議的純 Java 驅動程序。
第三、四兩類都是純Java的驅動程序,
因此,對於Java開發者來說,它們在性能、可移植性、功能等方面都有優勢。
ODBC
早期對數據庫的訪問,都是調用數據庫廠商提供的專有的 API。為了在 Windows 平台下提供統一的訪問方式,微軟推出了 ODBC(Open Database Connectivity,開放式數據庫連接),並提供了 ODBC API,使用者在程序中只需要調用 ODBC API,由 ODBC 驅動程序將調用轉換成為對特定的數據庫的調用請求。
一個基於ODBC的應用程序對數據庫的操作不依賴任何DBMS(database manager system),不直接與DBMS打交道,所有的數據庫操作由對應的DBMS的ODBC驅動程序完成。也就是說,不論是FoxPro、Access , MYSQL還是Oracle數據庫,均可用ODBC API進行訪問。由此可見,ODBC的最大優點是能以統一的方式處理所有的數據庫。
JDBC-ODBC橋
JDBC-ODBC 橋本身也是一個驅動,利用這個驅動,可以使用 JDBC-API 通過ODBC 去訪問數據庫。這種機制實際上是把標准的 JDBC 調用轉換成相應的 ODBC 調用,並通過 ODBC 訪問數據庫。
因為需要通過多層調用,所以利用 JDBC-ODBC 橋訪問數據庫的效率較低。
在 JDK 中,提供了 JDBC-ODBC 橋的實現類(sun.jdbc.odbc.JdbcOdbcDriver)。
部分本地API部分Java的驅動程序
- 這種類型的 JDBC 驅動程序使用 Java 編寫,它調用數據庫廠商提供的本地 API。
- 通過這種類型的 JDBC 驅動程序訪問數據庫減少了 ODBC 的調用環節,提高了數據庫訪問的效率。
- 在這種方式下需要在客戶的機器上安裝本地 JDBC 驅動程序和特定廠商的本地 API 。
JDBC網絡純Java驅動程序
這種驅動利用中間件的應用服務器來訪問數據庫。應用服務器作為一個到多個數據庫的網關,客戶端通過它可以連接到不同的數據庫服務器。
應用服務器通常有自己的網絡協議,Java 用戶程序通過 JDBC 驅動程序將 JDBC 調用發送給應用服務器,應用服務器使用本地程序驅動訪問數據庫,從而完成請求。
本地協議的純 Java 驅動程序
多數數據庫廠商已經支持允許客戶程序通過網絡直接與數據庫通信的網絡協議。
這種類型的驅動程序完全使用 Java 編寫,通過與數據庫建立的 Socket 連接,采用具體與廠商的網絡協議把 JDBC 調用轉換為直接連接的網絡調用。
JDBC API
JDBC API 是一系列的接口,它使得應用程序能夠進行數據庫聯接,執行SQL語句,並且得到返回結果。
Driver 接口
Java.sql.Driver 接口是所有 JDBC 驅動程序需要實現的接口。
- 這個接口是提供給數據庫廠商使用的,不同數據庫廠商提供不同的實現。
- 在程序中不需要直接去訪問實現了 Driver 接口的類,而是由驅動程序管理器類(java.sql.DriverManager)去調用這些Driver實現。
加載與注冊 JDBC 驅動
- 加載 JDBC 驅動需調用 Class 類的靜態方法 forName(),向其傳遞要加載的 JDBC 驅動的類名。
- DriverManager 類是驅動程序管理器類,負責管理驅動程序。
- 通常不用顯式調用 DriverManager 類的 registerDriver() 方法來注冊驅動程序類的實例,因為 Driver 接口的驅動程序類都包含了靜態代碼塊,在這個靜態代碼塊中,會調用 DriverManager.registerDriver() 方法來注冊自身的一個實例。
建立連接
可以調用 DriverManager 類的 getConnection() 方法建立到數據庫的連接。
JDBC URL 用於標識一個被注冊的驅動程序,驅動程序管理器通過這個 URL 選擇正確的驅動程序,從而建立到數據庫的連接。
JDBC URL的標准由三部分組成,各部分間用冒號分隔。
jdbc:<子協議>:<子名稱>
- 協議:JDBC URL中的協議總是jdbc
- 子協議:子協議用於標識一個數據庫驅動程序
- 子名稱:一種標識數據庫的方法。子名稱可以依不同的子協議而變化,用子名稱的目的是為了定位數據庫提供足夠的信息。
幾種常用數據庫的JDBC URL
- 對於 Oracle 數據庫連接,采用如下形式: jdbc:oracle:thin:@localhost:1521:sid。
- 對於 SQLServer 數據庫連接,采用如下形式: jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid。
- 對於 MYSQL 數據庫連接,采用如下形式: jdbc:mysql://localhost:3306/sid。
舉例子說明連接數據庫的幾種方式:
准備工作:
1. 加入 mysql 驅動
1). 解壓 mysql-connector-java-5.1.7.zip
2). 在當前項目下新建 lib 目錄
3). 把 mysql-connector-java-5.1.7-bin.jar 復制到 lib 目錄下
4). 右鍵 build-path , add to buildpath 加入到類路徑下.s
jdbc.properties文件
#driver=oracle.jdbc.driver.OracleDriver #jdbcUrl=jdbc:oracle:thin:@localhost:1521:orcl #user=scott #password=java driver=com.mysql.jdbc.Driver jdbcUrl=jdbc:mysql://localhost:3306/soyoungboy user=root password=1230
方式1:
DriverManager 是驅動的管理類.
1). 可以通過重載的 getConnection() 方法獲取數據庫連接. 較為方便
2). 可以同時管理多個驅動程序: 若注冊了多個數據庫連接, 則調用 getConnection()
方法時傳入的參數不同, 即返回不同的數據庫連接。
public Connection getConnection2() throws Exception{ //1. 准備連接數據庫的 4 個字符串. //1). 創建 Properties 對象 Properties properties = new Properties(); //2). 獲取 jdbc.properties 對應的輸入流 InputStream in = this.getClass().getClassLoader().getResourceAsStream("jdbc.properties"); //3). 加載 2) 對應的輸入流 properties.load(in); //4). 具體決定 user, password 等4 個字符串. String user = properties.getProperty("user"); String password = properties.getProperty("password"); String jdbcUrl = properties.getProperty("jdbcUrl"); String driver = properties.getProperty("driver"); //2. 加載數據庫驅動程序(對應的 Driver 實現類中有注冊驅動的靜態代碼塊.) Class.forName(driver); //3. 通過 DriverManager 的 getConnection() 方法獲取數據庫連接. return DriverManager.getConnection(jdbcUrl, user, password); }
方式二:
public void testDriverManager() throws Exception{ //1. 准備連接數據庫的 4 個字符串. //驅動的全類名. String driverClass = "com.mysql.jdbc.Driver"; //JDBC URL String jdbcUrl = "jdbc:mysql:///test"; //user String user = "root"; //password String password = "1230"; //2. 加載數據庫驅動程序(對應的 Driver 實現類中有注冊驅動的靜態代碼塊.) Class.forName(driverClass); //3. 通過 DriverManager 的 getConnection() 方法獲取數據庫連接. Connection connection = DriverManager.getConnection(jdbcUrl, user, password); System.out.println(connection); }
方式三:
public void testDriver() throws SQLException { //1. 創建一個 Driver 實現類的對象 Driver driver = new com.mysql.jdbc.Driver(); //2. 准備連接數據庫的基本信息: url, user, password String url = "jdbc:mysql://localhost:3306/test"; Properties info = new Properties(); info.put("user", "root"); info.put("password", "1230"); //3. 調用 Driver 接口的 connect(url, info) 獲取數據庫連接 Connection connection = driver.connect(url, info); System.out.println(connection); }
方式四:編寫一個通用的方法, 在不修改源程序的情況下, 可以獲取任何數據庫的連接
解決方案: 把數據庫驅動 Driver 實現類的全類名、url、user、password 放入一個配置文件中, 通過修改配置文件的方式實現和具體的數據庫解耦。
*/ public Connection getConnection() throws Exception{ String driverClass = null; String jdbcUrl = null; String user = null; String password = null; //讀取類路徑下的 jdbc.properties 文件 InputStream in = getClass().getClassLoader().getResourceAsStream("jdbc.properties"); Properties properties = new Properties(); properties.load(in); driverClass = properties.getProperty("driver"); jdbcUrl = properties.getProperty("jdbcUrl"); user = properties.getProperty("user"); password = properties.getProperty("password"); //通過反射常見 Driver 對象. Driver driver = (Driver) Class.forName(driverClass).newInstance(); Properties info = new Properties(); info.put("user", user); info.put("password", password); //通過 Driver 的 connect 方法獲取數據庫連接. Connection connection = driver.connect(jdbcUrl, info); return connection; }