下面用一個統一的工具類封裝一套用於數據庫的JDBC操作:包括 1)獲取數據庫鏈接資源 2)釋放數據庫鏈接資源,包括Connection,Statement,PreparedStatement,ResultSet等 3)數據庫的更新操作,包括插入,刪除,修改 4)數據庫的查詢操作
首先是1)獲取數據庫鏈接資源
/** * 獲取數據庫鏈接的靜態方法 這樣子就保證了只加載一次文件的操作 * @return * @throws Exception */ public static Connection getConn() throws Exception{ String jdbcDriver=null; String url=null; String user=null; String password=null; Properties p=new Properties(); InputStream is= JDBCTools.class.getClassLoader().getResourceAsStream("jdbc.properties"); p.load(is); jdbcDriver=p.getProperty("jdbcDriver"); url=p.getProperty("url"); user=p.getProperty("user"); password=p.getProperty("password"); Class.forName(jdbcDriver); return DriverManager.getConnection(url, user, password); }
其中 jdbc.properties 是屬性配置文件,因為是通過 類名.class.getClassLoader().getResourceAsStream("jdbc.properties");獲取的,所以
該屬性配置文件需要放置在src目錄下。其內容的例子:
jdbcDriver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
user=root
password=root
接著是2)釋放數據庫鏈接資源
/** * 關閉從數據庫服務器等索取的資源:先關閉後獲取的 * @param conn * @param pstmt */ public static void closeResource(Connection conn,Statement stmt,ResultSet rs){ if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } }
由於PreparedStatement是Statement的子接口,所以該方法也適合傳入PreparedStatement的對象
然後是3)數據庫的更新操作,包括插入,刪除,修改
/** * 統一的更新操作 Statement:insert update delete * @param conn * @param sql * @throws Exception */ public void update(String sql){ Connection conn=null; Statement stmt=null; try { conn=JDBCTools.getConn(); stmt=conn.createStatement(); stmt.executeUpdate(sql); } catch (Exception e) { e.printStackTrace(); } finally{ closeResource(conn, stmt, null); } } /** * 適用於PreparedStatment * @param sql * @param args */ public void update2(String sql,Object ... args){ Connection conn=null; PreparedStatement pstmt=null; ResultSet rs=null; try { conn=JDBCTools.getConn(); pstmt=conn.prepareStatement(sql); for(int i=0;i<args.length;i++){ pstmt.setObject(i+1, args[i]); } pstmt.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally{ JDBCTools.closeResource(conn, pstmt, rs); } }
其中這段代碼:for(int i=0;i<args.length;i++){ pstmt.setObject(i+1, args[i]); } 的意思在於:設置SQL語句中的占位符 ? 的值。
最後是4)數據庫的查詢操作:在這裡寫了通用的方法,目的在於將查詢得到的結果集封裝在統一的實體中,這裡采用了泛型,反射機制的知識
/** * 泛型方法 反射機制 通用的查詢方法存儲實體 * @param clazz * @param sql * @param args * @return */ public <T> T getT(Class<T> clazz,String sql,Object ... args){ T t=null; Connection conn=null; PreparedStatement pstmt=null; ResultSet rs=null; ResultSetMetaData rsmd=null; try { conn=JDBCTools.getConn(); pstmt=conn.prepareStatement(sql); for(int i=0;i<args.length;i++){ pstmt.setObject(i+1, args[i]); } rs=pstmt.executeQuery(); if (rs.next()) { t=clazz.newInstance(); Map<String, Object> map=new HashMap<String, Object>(); //解析sql獲取對象 rsmd = rs.getMetaData(); int numberOfColumns = rsmd.getColumnCount(); for(int i=0;i<numberOfColumns;i++) {
//獲取列的名字,如果有別名,則獲取的是別名 String columnName=rsmd.getColumnLabel(i+1); map.put(columnName, rs.getObject(columnName)); } if (map.size() > 0) { for(Map.Entry<String, Object> entry: map.entrySet()) { String columnName=entry.getKey(); Object columnValue=entry.getValue(); Field field = t.getClass().getDeclaredField(columnName); field.setAccessible(true); field.set(t, columnValue); } } } } catch (Exception e) { e.printStackTrace(); } finally{ JDBCTools.closeResource(conn, pstmt, rs); } return t; }