首先要「做得到」,然後才想「做得好」,這個範例止於「做得到」範疇,想深入鑽研如何「做得好」,文章最後會有額外提示。
廢話到此為止,開始之前,輸入資料,然後備份。你都懂的,不會的話,請回去前幾 PART 溫習。
———————————簡易的分隔線————————————
運行設定及預備圖片︰
【Run】 --> 【Run Configurations】
確認 Project 及 Main class 是否選對。
有【Embedded Mode】及【Client / Server Mode】吧? 複製一份。
改名及打上 Arguments,然後 Apply,這是【Embedded Mode】設定。
重覆以上動作,修改設定 ( 還記得 DERBY_OPTS 嗎?這是告訴 Derby 放 Database 的位置)。
好了,現在應該有一個 Embedded 及 Server 版設定,沒甚麼,只是 Argument 不同,方便測試。console output encoding,一定要設好,不然 console 會出亂碼。
修改程式碼或跟圖中路徑存放檔案,之後 write BLOB 範例中會用到。
———————————簡易的分隔線————————————
運行 Client / Server Mode︰
連接方法視乎 Argument 輸入而定,Embedded 之前 SQL 教學時用過,這次就用 Client / Server Driver。
首先開啟 Derby Network Server,要用合適權限執行,否則會失敗,會有開不到 derby.log 之類的 error message 出現。
這是成功開啟 Derby Network Server 畫面,以供參考。
在【Run Configurations】執行過一次後,可以在 ToolsBar 按下箭頭選 Profile 執行程式。
———————————簡易的分隔線————————————
程式碼解說︰
JDBC Driver︰
不需要在【Data Source Explorer】連線資料庫,因為直接以【SQL URL】連接,之前【Run Configurations】設定好。
相反,在【Data Source Explorer】連接資料庫,會令程式連不到資料庫,出現 Exception。所以﹐執行程式前,記謹斷開所有資料庫連線。
———————————簡易的分隔線————————————
執行次序︰
不完善的範例,不跟順序執行會發生錯誤,反正是展示用,略過 error checking、exception handling、logic 等等。
雖然寫【Press any else key to exit program】,輸入不是數字會有 exception。
———————————簡易的分隔線————————————
執行過程及結果︰
時間軸 | 註解 |
---|---|
0:00 | 預備測試用圖檔 ( insert.jpg ) |
0:25 | 檢查 Run Configurations 設定 |
1:29 | 執行 Derby Network Server |
2:09 | 執行程式 |
時間軸 | Select case | 註解 |
---|---|---|
2:27 | case 1 read | 讀取資料,檢視資料狀態 |
2:58 | case 3 write | 寫入 BLOB ( insert.jpg ) 同時寫入其他資訊 ( 檔案名稱連副檔名, etc ) |
3:09 | case 1 read | 再次讀取資料,觀看寫入結果 |
3:24 | case 2 delete | 刪除指定資料 |
3:35 | case 1 read | 檢視刪除後結果 |
3:51 | case 4 update BLOB | 更新 BLOB Type 資料 |
4:07 | case 5 Extract BLOB | 滙出 BLOB 資料 |
———————————簡易的分隔線————————————
Connection、Statement / PreparedStatement、ResultSet 及 ResultSetMetaData 關係︰
Connection︰
以【Connection URL】設定 JDBC Driver,用這範例來說,用 Properties 把 User Name 及 Password 連接 指定的 Database。連接成功後,要做甚麼?執行 SQL 指令……怎做?這時候需要用 Connection 建立 Statement / PreparedStatement。
Connecting to databases within the system
https://db.apache.org/derby/docs/10.14/devguide/cdevdvlp846369.html
Statement / PreparedStatement︰
Statement 這個很容易理解,建立好之後,用 execute() 或 executeQuery() 執行 SQL。
用 Statement 可以做到,為甚麼還有 PreparedStatement?因為不知道實際 value 是甚麼,本範例來說,不會知道檔案名稱,所以不能把 SQL 寫死。
用 SQL 建立 PreparedStatement 時,以【?】作為變數,跟據輸入做點手腳,最後設定變數把 SQL 完成。另外,PreparedStatement 也是 Object,重用 Object 比每次建立新 Object 效能會比較好。
Prepared statements and streaming columns
https://db.apache.org/derby/docs/10.14/ref/rrefjavsqlprst.html
ResultSet︰
例如 INSERT 只有成功與否,但用 SELECT 呢?會回傳結果,那個結果用 ResultSet 接住。statement.executeQuery() 回傳 ResultSet,得到 ResultSet 後可以做甚麼?看 API 文件。
Interface ResultSet
https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
ResultSetMetaData︰
得到 ResultSet 後,怎知道入面的 Data Types?為甚麼要知道 Data Types?
讀取 ResultSet,需要用 getXXX 之類 method 撈資料,不知道資料 Data Types 就不知道用甚麼 method 取得資料。知道 Data Types 方法有兩個,一是記得資訊結構,例如 table schema,另一個方法是用 ResultSetMetaData。
Supported Data Types
https://docs.oracle.com/cd/E19501-01/819-3659/gcmaz/
Interface ResultSetMetaData
https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSetMetaData.html
———————————簡易的分隔線————————————
Best practice tips︰
ASAP release resource ( connection, resultset, etc )︰
網絡不穩定,不知道何時會斷線時,程式又不懂重新連線,有機會發生 Null pointer Exception。
不需要頻繁讀寫 Database,而長期佔用連線也是個問題,database 有連線上限數,不斷建立連線,又不釋放資源,會導致程式及資料庫崩潰。
所以最好完成一連串動作後,要把連線斷開,通知 JVM 做 Garbage Collection ( GC ) 釋放資源,有需要時才重新連線。
result_set.close();
prepare_statment.close();
connection.close();
GC 不到你控制,JVM 何時真正釋放資源,你不會知道,就算程式碼順序寫 close ResultSet 到 PrepareStatment 最後到 Connection,也不知道 GC 是不是順序釋放資源。這個動作只為了通知 JVM 可以回收 Object,免得資源被鎖死。
Use connection pool︰
經常斷線連線,重用 Object 是個好選擇,有機會把 DriverManager.getConnection() 連線方式,改造成
Connection con = datasource.getConnection( username, password );
datasource 有很多選擇,跟據需要選擇合適 Datasource,有些 datasource 可以配合 JNDI 及 J2EE Container ( Tomcat 之類 ) 一起使用。
Apache Derby 10.14 API Documentation
https://db.apache.org/derby/docs/10.14/publishedapi/index.html
Getting a DataSource
https://db.apache.org/derby/docs/10.14/devguide/cdevresman89722.html
Derby Network Client
https://db.apache.org/derby/papers/DerbyClientSpec.html#-N100AC
ClientConnectionPoolDataSource
https://db.apache.org/derby/docs/10.14/publishedapi/org/apache/derby/jdbc/ClientConnectionPoolDataSource.html
Data Access Object ( DAO )︰
簡單來說,做 ORM ( Object Relational Mapping )。把所有 SQL 包裝成 DAO 尾的 Class,把 SQL 細節偽裝成為普通的 getter / setter method 使用,實際怎做,看參考。
當要轉換 Database 時 (例如 Derby 轉去 Mysql ),把所有 DAO 尾的 Class 檢視及修改 ( search 檔案含 DAO 字眼,很簡單找齊 ),理論上可以無痛轉換。除非用了database specific 的 SQL 語法。
Object-relational mapping - Wikipedia
https://en.wikipedia.org/wiki/Object-relational_mapping
Data Access Object
http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/dao.html
SQL dialect 及 EJB-QL︰
都是避免 vendor lock-in 的技術,沒有深入研究,只是轉換 database 成本比想像中還要高,所以一開始,最好考慮一下將來會不會因為轉不到 vendor,被人開天殺價。
———————————簡易的分隔線————————————
總結︰
學會 database 後,然後是怎應用 database,例如︰
- 輸入資料︰制作 GUI 連接 Database ( 網頁連接資料庫、手機 Apps 連接資料庫、桌面應用程式連接資料庫等等 )
- 輸出資料︰JasperReport 連接 Database 制作 Report
沒有留言:
發佈留言
設有留言驗證及審查,檢閱後,才會顯示留言。
本人惰性很高,留言或許會石沉大海。