Java JDBC 使用 SQLite/操作資料
JDBC 提供了許多不同的方法來處理資料和資料物件操作。通常這些方法分為三類:代理 Prepared 語句的方法,期望從資料庫返回資料的的方法(這些方法總是會返回一個 ResultSet),以及最後是在不期望返回資訊的情況下對資料庫進行操作的方法,例如建立一個表或從表中刪除一些資料。
使用 PreparedStatement (PS) 方法與資料庫互動有充分的理由,特別是當互動重複時,因為 PS 會被髮送到資料庫進行編譯,這意味著在隨後的呼叫中,資料庫可以訪問呼叫而無需重新編譯,從而導致更快的執行時間。
與使用與 Connection 物件關聯的 Statements 的其他方法呼叫一樣,PreparedStatement 也與 Connection 相關聯。
[.. pseudocode ..]
Connection conn = new Connection(); // whatever it might be
String psString = "UPDATE myTable SET myText = 'First Update'";
String psStringWithParms = "UPDATE myTable SET myText = ?";
// prepare & execute the psString
PreparedStatement ps = conn.prepareStatement(psString);
ps.executeUpdate();
// now we will overwrite this using the parameterised psString
PreparedStatement psParms = conn.prepareStatement(psStringWithParms);
psParms.setString(1,"Revised update");
psParms.executeUpdate();
在與資料庫互動時,經常會遇到不知道列名或給定 SQL 查詢將返回的資料型別的場景。幸運的是,JDBC 類提供了兩個非常有用的介面,可以利用它們來解決這個問題:ResultSetMetaData 和 DatabaseMetaData。
可以在此處找到結果集介面的 Java 文件:[1]。該介面在任何給定的結果集例項中都能夠有效地暴露列名和資料型別(以及更多內容)。
例如,可以使用以下示例方法來暴露列名
public static String[] getColumnNameArray(ResultSet rs) {
String sArr[] = null;
try {
ResultSetMetaData rm = rs.getMetaData();
String sArray[] = new String[rm.getColumnCount()];
for (int ctr = 1; ctr <= sArray.length; ctr++) {
String s = rm.getColumnName(ctr);
sArray[ctr - 1] = s;
}
return sArray;
} catch (Exception e) {
System.out.println(e);
return sArr;
}
}
可以對資料型別做同樣的事情
public static String[] getColumnTypeArray(ResultSet rs) {
String sArr[] = null;
try {
ResultSetMetaData rm = rs.getMetaData();
String sArray[] = new String[rm.getColumnCount()];
for (int ctr = 1; ctr <= sArray.length; ctr++) {
String s = rm.getColumnTypeName(ctr);
sArray[ctr - 1] = s;
}
return sArray;
} catch (Exception e) {
System.out.println(e);
return sArr;
}
}
透過使用 ResultSetMetaData 的 getColumnCount() 方法,可以避免不必要的將資料傳遞到 Vector 並重新轉換為 String[] 陣列,因為可以直接從一開始就適當地調整 String[] 陣列的大小。
到目前為止,你可能已經注意到,除了呼叫的 ResultSetMetaData 方法外,這兩段程式碼在功能上幾乎相同,可以在這裡進行一些合理化,例如使用一個處理迭代的第三個方法,或者可能使用 java.lang.reflect 動態載入方法。在生產系統中,你可能希望避免在反射中增加 JVM 的工作量(Java 反射本身很昂貴),但可以輕鬆地編寫一個 switch 塊來完成適當的簡化,傳遞一個額外的引數來指示在構造 String[] 陣列時要呼叫哪個方法。
現在,讓我們透過假設正在建立一個名為 testme 的資料庫表的查詢類,並且不知道它的列名和型別來將這些程式碼整合在一起。
import java.sql.ResultSetMetaData;
public class MyDbTest
{
public void main(String[] args)
{
SqliteDb db = new Sqlite("C:/DbStore/test.db");
String sqltest = "SELECT * FROM testme";
Vector<Object> v = new Vector<Object>();
try
{
ResultSet rs = db.executeQry(sqltest);
String[] columnNames = getColumnNameArray(rs);
String[] columnTypes = getColumnTypeArray(rs);
//iterate the rows in the result set...
while(rs.next())
{
// now walk each column in the array...
for (int i = 1; i < columnNames.length; i++)
{
Object o = rs.getObject(columnNames[i]);
if (columnTypes[i].toUpper().equals("VARCHAR"))
{
sVal = o.toString();
}
[etcetera ..]
[..]
}
}
catch (Exception e)
{
[..]
}
}
有關列型別的完整列表,請參閱附錄。