持久化(persistence):把資料保存到可掉電式儲存裝置中以供之後使用。大多數情況下,特別是企業級應用,資料持久化意味著將記憶體中的資料保存到硬碟上加以」固化”,而持久化的實現過程大多透過各種關聯式資料庫來完成。
持久化的主要應用是將記憶體中的資料儲存在關係型資料庫中,當然也可以儲存在磁碟檔案、XML資料檔案中。
在Java中,資料庫存取技術可分為如下幾類:
JDBC直接存取資料庫
JDOs
O/Rate , ibatis 等
JDBC是java存取資料庫的基石,JDO, Hibernate等只是更好的封裝了JDBC。
JDBC(Java Database Connectivity)是一個獨立於特定資料庫管理系統、通用的SQL資料庫存取和操作的公共介面(一組API),定義了用來存取資料庫的標準Java類別庫(java.sql,javax.sql)使用這個類別庫可以以一種標準的方法、方便地存取資料庫資源JDBC為存取不同的資料庫提供了一種統一的途徑,為開發者屏蔽了一些細節問題。
JDBC的目標是使Java程式設計師使用JDBC可以連接任何提供了JDBC驅動程式的資料庫系統,這樣就使得程式設計師無需對特定的資料庫系統的特點有過多的了解,從而大大簡化和加快了開發過程。
JDBC介面(API)包含兩個層次:
面向應用的API:Java API,抽象介面,供應用程式開發人員使用語句連接程式碼,執行程式碼連線獲得結果)。
面向資料庫的API:Java Driver API,供開發人員開發資料庫驅動程式使用。
JDBC是sun公司提供一套用於資料庫操作的接口,java程式設計師只需要面向這套接口編程即可。不同的資料庫廠商,需要針對這套接口,提供不同實作。不同的實作的集合,即為不同資料庫的驅動。 ————面向介面程式設計
JDBC驅動程式:各個資料庫廠商依據JDBC的規格所製作的 JDBC 實作類別的類別庫
JDBC驅動程式總共有四種類型:
第二類:部分本機API部分Java的驅動程式。 第三類:JDBC網路純Java驅動程式。
第四類:本地協定的純 Java 驅動程式。
早期對資料庫的訪問,都是呼叫資料庫廠商提供的專有的 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 驅動程式使用Java 編寫,它呼叫資料庫廠商提供的本地API透過這種類型的JDBC 驅動程式存取資料庫減少了ODBC 的呼叫環節,提高了資料庫存取的效率在這種方式下需要在客戶的機器上安裝本機JDBC 驅動程式和特定廠商的本機API 。
這種驅動利用中間件的應用伺服器來存取資料庫。應用程式伺服器作為一個到多個資料庫的網關,客戶端透過它可以連接到不同的資料庫伺服器。
應用伺服器通常有自己的網路協議,Java 用戶程式透過 JDBC 驅動程式將 JDBC 呼叫傳送給應用伺服器,應用程式伺服器使用本地程式驅動存取資料庫,從而完成請求。
多數資料庫廠商已經支援允許客戶程式透過網路直接與資料庫通訊的網路協定。
這種類型的驅動程式完全使用 Java 編寫,透過與資料庫建立的 Socket 連接,採用具體與廠商的網路協定把 JDBC 呼叫轉換為直接連接的網路呼叫JDBC API。
JDBC API 是一系列的接口,它使得應用程式能夠進行資料庫聯接,執行SQL語句,並且得到返回結果。
java.sql.Driver 介面是所有 JDBC 驅動程式需要實作的介面。這個介面是提供給資料庫廠商使用的,不同資料庫廠商提供不同的實作在程式中不需要直接去存取實作了Driver 介面的類,而是由驅動程式管理器類(java.sql.DriverManager)去呼叫這些Driver實作。
Oracle的驅動:oracle.jdbc.driver.OracleDriver
mySql的驅動: com.mysql.jdbc.Driver
方式一:加載JDBC 驅動需呼叫Class 類別的靜態方法forName(),傳遞要載入的JDBC 驅動程式的類別名稱
Class.forName(“com.mysql.jdbc.Driver”);
.jdbc.Driver”);
DriverManager.registerDriver(com.mysql.jdbc.Driver);
通常不使用明確呼叫的實例,因為Driver 介面的驅動程式類別都包含了靜態程式碼區塊,在這個靜態程式碼區塊中,會呼叫DriverManager.registerDriver() 方法來註冊自身的一個實例。
建立連線(Connection)
可以呼叫 DriverManager 類別的 getConnection() 方法建立到資料庫的連線。
User,password可以用「屬性名=屬性值」方式告訴資料庫;JDBC URL 用於標識一個被註冊的驅動程序,驅動程式管理器透過這個URL 選擇正確的驅動程序,從而建立到資料庫的連線。
JDBC URL的標準由三個部分組成,各部分間以冒號分隔。
jdbc:子協定:子名稱
協定:JDBC URL中的協定總是jdbc 。
jdbc:mysql://localhost:3306/test
協定子協定 子名稱 : oracle:thin:@localhost:1521:atguigu
對於SQLServer 資料庫連接,採用如下形式:
jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sidjdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sidjdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid? :
jdbc:mysql://localhost:3306/atguigu
Statement
一旦取得了連線物件也必須執行物件時間。
Connection connection = getConnection(); Statement state = connection.createStatement(); int n = state.executeUpdate(“insert,update,delete…”);
SQL 注入攻擊性
SQL某些系統沒有對使用者輸入的資料進行充分的檢查,而在使用者輸入資料中註入非法的SQL 語句段或命令(如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1') ,從而利用系統的SQL 引擎完成惡意行為的做法對於Java 而言,要防範SQL 注入,只要用PreparedStatement(從Statement擴展而來)
就可以了取代 Statement 。
3-使用PreparedStatement
資料型態轉換表
可以透過呼叫Connection 物件的preparedStatement() 方法來取得PreparedStatement 對象。
PreparedStatement 介面是 Statement 的子接口,它表示一條預先編譯過的 SQL 語句。PreparedStatement vs Statement
程式碼的可讀性和可維護性.
SerreparedStatement 能提供功能性高程式碼因為預編譯語句有可能被重複調用,所以語句在被DBServer的編譯器編譯後的執行程式碼被快取下來,那麼下次調用時只要是相同的預編譯語句就不需要編譯,只要將參數直接傳入編譯過的語句執行程式碼中就會執行。
在statement語句中,即使是相同操作但因為資料內容不一樣,所以整個語句本身不能匹配,沒有快取語句的意義。事實是沒有資料庫會對普通語句編譯後的執行程式碼快取.這樣每執行一次都要對傳入的語句編譯一次。 (語法檢查,語意檢查,翻譯成二進位指令,快取)。 PreparedStatement
可以防止SQL 注入 連線資料庫、操作表的步驟:
建立執行SQL的語句(PreparedStatement )
理執行結果(ResultSet)
理執行結果(ResultSet)
Connection conn = null; PreparedStatement st=null; ResultSet rs = null; try { //获得Connection //创建PreparedStatement //处理查询结果ResultSet }catch(Exception e){ e.printStackTrance(); } finally { //释放资源ResultSet, // PreparedStatement , //Connection
释放ResultSet, PreparedStatement ,Connection。
数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
ORM:Object Relation Mapping
表 与 类 对应
表的一行数据 与 类的一个对象对应
表的一列 与类的一个属性对应
通过调用 PreparedStatement 对象的 excuteQuery() 方法创建该对象。
ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商实现。
ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。
ResultSet 接口的常用方法:
boolean next()
getString()
…
处理执行结果(ResultSet)
读取(查询)对应SQL的SELECT,返回查询结果
st = conn.createStatement(); String sql = "select id, name, age,birth from user"; rs = st.executeQuery(sql); while (rs.next()) { System.out.print(rs.getInt("id") + " \t "); System.out.print(rs.getString("name") + " \t"); System.out.print(rs.getInt("age") + " \t"); System.out.print(rs.getDate(“birth") + " \t "); System.out.println();} }
关于Result的说明
1. 查询需要调用 Statement 的 executeQuery(sql) 方法,查询结果是一个 ResultSet 对象
2. 关于 ResultSet:代表结果集
ResultSet: 结果集. 封装了使用 JDBC 进行查询的结果. 调用 Statement 对象的 executeQuery(sql) 可以得到结果集.
ResultSet 返回的实际上就是一张数据表. 有一个指针指向数据表的第一条记录的前面.
3.可以调用 next() 方法检测下一行是否有效. 若有效该方法返回 true, 且指针下移. 相当于Iterator 对象的 hasNext() 和 next() 方法的结合体
4.当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值.
例如: getInt(1), getString("name")
5.ResultSet 当然也需要进行关闭.
MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)。
实际使用中根据需要存入的数据大小定义不同的BLOB类型。
需要注意的是:如果存储的文件过大,数据库的性能会下降。
可用于获取关于 ResultSet 对象中列的类型和属性信息的对象。
ResultSetMetaData meta = rs.getMetaData();
getColumnName(int column):获取指定列的名称
getColumnLabel(int column):获取指定列的别名
getColumnCount():返回当前 ResultSet 对象中的列数。
getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
isNullable(int column):指示指定列中的值是否可以为 null。
isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。
java.sql.DriverManager用來裝載驅動程序,取得資料庫連線。
java.sql.Connection完成對某一指定資料庫的連線。
java.sql.Statement在一個給定的連接中作為SQL執行聲明的容器,他包含了兩個重要的子類型。
Java.sql.PreparedSatement 用於執行預編譯的sql聲明。
Java.sql.CallableStatement用於執行資料庫中預存程序的呼叫。
java.sql.ResultSet對於給定聲明取得結果的途徑。
兩種思想
面向接口編程的思想;
面向接口編程的思想;
兩種技術
JDBC元資料:ResultSetMClass
JDBC元資料:ResultSetMClassDataMWClass,透過列的工具給創建的物件。
5-批次處理
批次處理JDBC語句提高處理速度 。
JDBC的批次處理語句包括下面兩個方法:
addBatch(String):新增需要批次的SQL語句或參數;
executeBatch():執行批次處理語句;clearBatch():清空快取的資料;
通常我們會遇到兩種批次執行SQL語句的情況:
多條SQL語句的一個批次的一個批次;語句的批次傳參;
6-資料庫連接池
JDBC資料庫連接池的必要性的模式基本上是以下步驟:
在主程式(如servlet、beans)建立資料庫連線
進行sql操作
斷開資料庫連線
的JDBC資料庫連線使用DriverManager 來獲取,每次向資料庫建立連線的時候都要將Connection 載入到記憶體中,再驗證使用者名稱和密碼(得花費0.05s~1s的時間)。需要資料庫連線的時候,就向資料庫要求一個,執行完成後再斷開連線。這樣的方式將會消耗大量的資源和時間。資料庫的連接資源並沒有很好的重複利用.若同時有幾百人甚至幾千人在線,頻繁的進行資料庫連接操作將佔用很多的系統資源,嚴重的甚至會造成伺服器的崩潰。每一次資料庫連接,使用完後都得斷開。否則,如果程式出現異常而未能關閉,將會導致資料庫系統中的記憶體洩漏,最終將導致重新啟動資料庫。這種開發不能控制被創建的連接物件數,系統資源會被毫無顧及的分配出去,如連接過多,也可能導致記憶體洩漏,伺服器崩潰。 資料庫連接池(connection pool)
為解決傳統開發中的資料庫連線問題,可採用資料庫連接池技術。 資料庫連線池的基本概念就是為資料庫連線建立一個「緩衝池」。預先在緩衝池中放入一定數量的連接,當需要建立資料庫連接時,只需從「緩衝池」中取出一個,使用完畢之後再放回去。
資料庫連接池負責分配、管理和釋放資料庫連接,它允許應用程式重複使用一個現有的資料庫連接,而不是重新建立一個。
資料庫連線池在初始化時將建立一定數量的資料庫連線放到連線池中,這些資料庫連線的數量是由最小資料庫連線數來設定的。無論這些資料庫連線是否被使用,連線池都將一直保證至少擁有這麼多的連線數量。連接池的最大資料庫連線數量限定了這個連線池能佔有的最大連線數,當應用程式向連線池請求的連線數超過最大連線數量時,這些請求將會加入到等待佇列中。
資料庫連接池的工作原理
資料庫連接池技術的優點
更快的系統反應速度
資料庫連接池在初始化過程中,往往已經創建了若干資料庫連接置於連接池中備用。此時連線的初始化工作均已完成。對於業務請求處理而言,直接利用現有可用連接,避免了資料庫連接初始化和釋放過程的時間開銷,從而減少了系統的回應時間。
新的資源分配手段
對於多應用共享相同資料庫的系統而言,可在應用層透過資料庫連接池的配置,實現某一應用最大可用資料庫連接數的限制,避免某一應用程式獨佔所有的資料庫資源。
統一的連接管理,避免資料庫連接洩漏
在較為完善的資料庫連接池實現中,可根據預先的佔用超時設定,強制回收被佔用連接,從而避免了常規資料庫連接操作中可能出現的資源外洩。 兩種開源的資料庫連接池 :
JDBC 的資料庫連接池使用javax.sql.DataSource 來表示,DataSource 只是一個接口,該接口通常由伺服器(Weblogic, WebSphere, Tomcat)提供實現,也有一些開源組織提供實作:
DBCP 資料庫連線池
C3P0 資料庫連接池
DataSource 通常被稱為資料來源,它包含連接池和連接池管理兩個部分,習慣上也經常把 DataSource 稱為連接池。
DataSource用來取代DriverManager來取得Connection,取得速度快,同時可以大幅提高資料庫存取速度。
DBCP 資料來源
DBCP 是Apache 軟體基金組織下的開源連接池實現,該連接池依賴該組織下的另一個開源系統:Common-pool. 如需使用該連接池實現,應在系統中增加以下兩個jar 檔案:
Commons-dbcp.jar:連接池的實作
Commons-pool.jar:連接池實現的依賴庫
是採用該連線池來實現的。此資料庫連接池既可與應用程式伺服器整合使用,也可由應用程式獨立使用。 DBCP 資料來源使用範例
資料來源和資料庫連線不同,資料來源無需建立多個,它是產生資料庫連線的工廠,因此整個應用只需要一個資料來源即可。
當資料庫存取結束後,程式還是像以前一樣關閉資料庫連接:conn.close(); 但上面的程式碼並沒有關閉資料庫的實體連接,它僅僅把資料庫連接釋放,歸還給了資料庫連線池。
7-資料庫事務
事務:一組邏輯操作單元,使資料從一種狀態轉換到另一種狀態。
事務處理(事務操作):確保所有事務都作為一個工作單元來執行,即使出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操作時,要么所有的事務都被提交(commit),那麼這些修改就永久地保存下來;要么數據庫管理系統將放棄所做的所有修改,整個事務回滾(rollback)到最初狀態。
為確保資料庫中資料的一致性,資料的操縱應當是離散的成組的邏輯單元:當它全部完成時,資料的一致性可以保持,而當這個單元中的一部分操作失敗,整個事務應全部視為錯誤,所有從起始點以後的操作應全部回退到開始狀態。
事務的ACID(acid)屬性
1.原子性(Atomicity)
1.原子性(Atomicity)
原子是指事務中是一個不可分割的工作單位都不發生。
2. 一致性(Consistency)
事務必須使資料庫從一個一致性狀態轉換到另一個一致性狀態。
3. 隔離性(Isolation)
事務的隔離性是指一個事務的執行不能被其他事務幹擾,即一個事務內部的操作及使用的資料對並發的其他事務是隔離的,並發執行的各個事務之間不能互相干擾。
4. 持久性(Durability)
持久性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響JDBC 事務處理
當一個連接物件建立時,預設是自動提交事務:每次執行一個SQL 語句時,如果執行成功,就會向資料庫提交,而不能回滾。
為了讓多個SQL 語句作為一個事務執行:
呼叫Connection 物件的setAutoCommit(false); 以取消自動提交內容
語 commit(); 方法提交事務
在出現異常時,調用rollback(); 方法回滾事務
若此時Connection 沒有被關閉, 則需要恢復其自動提交狀態
若此時Connection 沒有被關閉, 則需要恢復其自動提交狀態 提交後的資料狀態
資料的改變已經被保存到資料庫中。
改變前的資料已經遺失。
所有使用者可以看到結果。
鎖被釋放, 其他使用者可以操作涉及到的資料。
將常用的操作資料庫的JDBC的類別和方法集合在一起,就是DBUtils.
: JavaBeanBeanBeanListHandler:把結果集轉為一個Bean 的集合
MapHandler:把結果集轉為一個Map
MapMapListHandler:把結果集轉為一個Map 的ListScalarHandler:把結果集轉為一個類型的結果集轉為一個類型的結果集。資料回傳, 此類型通常指String 或其它8 種基本資料類型.以上就是JDBC--資料庫管理系統的內容,更多相關內容請關注PHP中文網(www.php.cn) !