JAVA實現DAO基本層CRUD操作(轉)
阿新 • • 發佈:2020-07-21
轉載:https://www.cnblogs.com/yxwkf/p/4643483.html
以下詳細講講通過我自己的方式對有關DAO層資料庫基本CRUD操作的JAVA實現(此處已MySQL為例,其它資料庫僅僅需做部分改動就可以)。
備註:若要試用本演示樣例,僅僅需依照給出的順序依次複製程式碼建立對應的類就可以。另外。在專案lib資料夾下增加mysql連結jar包。
(1)定義資料來源常量類
package com.jkitn.jkits.common; /** * 定義資料來源常量類 * @author xdweleven * @version 1.0 */ public class JdbcConfig { /** 資料庫驅動 */ public static final String DRIVERCLASSNAME = "com.mysql.jdbc.Driver"; /** 資料庫URL */ public static final String URL = "jdbc:mysql://localhost:3306/app_jkit"; /** 資料庫username */ public static final String USERNAME = "root"; /** 資料庫password */ public static final String PASSWORD = "root"; }
(2)定義結果集(ResultSet)到pojo物件的對映
package com.jkitn.jkits.dao.common; import java.lang.reflect.Field; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * 說明:實現結果集到pojo物件的對映 * @author xdweleven * @version 1.0 */ public class RowMapper<T>{ private Class<T> objectClass; public RowMapper(Class<T> objectClass) { this.objectClass = objectClass; } /** * 實現單條記錄到物件的對映 * @param rs 結果集 * @param rowNum 當前行數 * @return * @throws SQLException */ public T mapRow(ResultSet rs, int rowNum) throws SQLException { try { T object = objectClass.newInstance(); // 得到結果集的欄位集合 ResultSetMetaData metaData = rs.getMetaData(); int columnNum = metaData.getColumnCount(); Field[] fields = object.getClass().getDeclaredFields(); // 設定物件屬性的值。若不存在。則設定為null. for (int i = 0; i < fields.length; i++) { Field field = fields[i]; int flag = 0; for (int j = 1; j <= columnNum; j++) { if (metaData.getColumnName(j).toLowerCase().equals(field.getName().toLowerCase())) { flag = 1; break; } } field.setAccessible(true); if (flag == 1) { this.typeMapper(field, object, rs); }else { field.set(object, null); } field.setAccessible(false); } return object; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; } /** * 實現多條記錄到結果集的對映 * @param rs * @return */ public List<T> mapRows(ResultSet rs){ int rowNum = 0; List<T> objList = new ArrayList<T>(); try { while(rs.next()){ objList.add(this.mapRow(rs, rowNum++)); } rs.close(); } catch (SQLException e) { e.printStackTrace(); } return objList; } /** * 型別的對映 * @param field * @param obj * @param rs * @throws IllegalArgumentException * @throws IllegalAccessException * @throws SQLException */ private void typeMapper(Field field, Object obj, ResultSet rs) { String typeName = field.getType().getName(); // 得到欄位型別 try { if (typeName.equals("java.lang.String")) { field.set(obj, rs.getString(field.getName())); } else if (typeName.equals("int") || typeName.equals("java.lang.Integer")) { field.set(obj, rs.getInt(field.getName())); } else if (typeName.equals("long") || typeName.equals("java.lang.Long")) { field.set(obj, rs.getLong(field.getName())); } else if (typeName.equals("float") || typeName.equals("java.lang.Float")) { field.set(obj, rs.getFloat(field.getName())); } else if (typeName.equals("double") || typeName.equals("java.lang.Double")) { field.set(obj, rs.getDouble(field.getName())); } else if (typeName.equals("boolean") || typeName.equals("java.lang.Boolean")) { field.set(obj, rs.getBoolean(field.getName())); } else if (typeName.equals("java.util.Date")) { field.set(obj, rs.getTimestamp(field.getName())); } else { } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } }
(3)定義資料庫連線輔助類DBConn
package com.jkitn.jkits.common; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import com.jkitn.jkits.dao.common.RowMapper; /** * 定義資料庫連線輔助類DBConn * @author xdweleven * @version 1.0 */ public class DBConn { private Connection conn = null; private PreparedStatement pstmt = null; private ResultSet rs = null; /** * 建立資料庫的連線 * @return 返回資料庫連線物件 */ public Connection getConn(){ try { // 載入資料庫驅動 Class.forName(JdbcConfig.DRIVERCLASSNAME); // 建立Connection介面物件。用於獲取MySQL資料庫的連線物件 conn = DriverManager.getConnection(JdbcConfig.URL, JdbcConfig.USERNAME, JdbcConfig.PASSWORD); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 更新資料庫操作(包含增刪改操作) * @param sql 待執行sql語句 * @param objs 用於設定預編譯語句中帶入的引數 * @return null * @throws Exception */ public int execUpdate(String sql, Object ...objs) throws Exception{ // 獲取預編譯環境 pstmt = this.getConn().prepareStatement(sql); if(objs != null && objs.length > 0){ for(int i = 0; i < objs.length; i++){ pstmt.setObject(i+1, objs[i]); } } // 執行更新語句 int result = pstmt.executeUpdate(); // 斷開連線。釋放資源 this.close(rs, pstmt, conn); return result; } /** * 資料庫查詢操作 * @param sql 待執行sql語句 * @param objs 用於設定預編譯語句中帶入的引數 * @return 類T的List資料型別,即返回查詢到的全部資料資訊 * @throws Exception */ public <T> List<T> execQuery(String sql, RowMapper<T> mapper, Object ...objs) throws Exception{ // 獲取預編譯環境 pstmt = this.getConn().prepareStatement(sql); if(objs != null && objs.length > 0){ for(int i = 0; i < objs.length; i++){ pstmt.setObject(i+1, objs[i]); } } // 執行更新語句 rs = pstmt.executeQuery(); // 執行關係到物件的對映 List<T> result = mapper.mapRows(rs); // 斷開連線。釋放資源 this.close(rs, pstmt, conn); return result; } /** * 執行執行的SQL語句並返回結果集 * @param sql SQL語句 * @param params 引數 * @return 返回結果集 */ public ResultSet queryForResultSet(String sql, Object... objs) throws Exception{ // 獲取預編譯環境 pstmt = conn.prepareStatement(sql); if(objs != null && objs.length > 0){ for(int i = 0; i < objs.length; i++){ pstmt.setObject(i+1, objs[i]); } } // 執行更新語句 rs = pstmt.executeQuery(); // 斷開連線,釋放資源 this.close(null, pstmt, conn); return rs; } /** * 關閉資料庫連線,釋放所佔的系統資源 * @param rs結果集、ppst預編譯命令、conn資料庫 * @return null * @throws Exception */ public void close(ResultSet rs, PreparedStatement ppst, Connection conn) throws Exception{ if(rs != null){ rs.close(); } if(ppst != null){ ppst.close(); } if(conn != null){ conn.close(); } } }
(4)定義通用分頁查詢實體類
package com.jkitn.jkits.common; import java.util.List; /** * 說明:實現通用分頁查詢實體類 * @author xdweleven * @version 1.0 */ public class PageBean<T> { private int totalRows; // 總記錄數 private int totalPages; // 總頁數 private int curPage; // 當前頁碼 private int prePage; // 上一頁頁碼 private int nextPage; // 下一頁頁碼 private int rowsPerPage; // 每頁顯示的記錄數 private List<T> pageList; // 當前頁的資料集 /** * 初始化分頁bean物件 * @param totalRows 總記錄數 * @param rowsPerPage 每頁顯示的記錄數 */ public void initPageBean(int totalRows, int rowsPerPage){ this.rowsPerPage = rowsPerPage; this.totalRows = totalRows; this.totalPages = (this.totalRows-1)/this.rowsPerPage + 1; // 設定上一頁 if(this.curPage == 1){ this.setPrePage(1); }else{ this.setPrePage(this.curPage-1); } // 設定下一頁 if(this.curPage == this.totalPages){ this.setNextPage(this.totalPages); }else{ this.setNextPage(this.curPage + 1); } } /** * 生成SQLServer的分頁查詢語句 * @param sql 原始sql語句 * @param curPage 第幾頁 * @param rowsPerPage 每頁多少行 */ public String getPageSQLServer(String sql, int curPage, int rowsPerPage){ String afterFrom = sql.toLowerCase().substring(sql.indexOf("from")); String pageSql = null; if(afterFrom.indexOf("where") == -1){ pageSql = "select top "+ rowsPerPage + " * "+afterFrom +" where id not in(select top "+rowsPerPage*(curPage-1)+" id " +afterFrom+" order by id desc)"+"order by id desc"; }else{ pageSql = "select top "+ rowsPerPage + " * "+afterFrom +" and id not in(select top "+rowsPerPage*(curPage-1)+" id " +afterFrom+" order by id desc)"+"order by id desc"; } return pageSql; } /** * 生成MySql分頁sql語句 * @param sql 原始sql語句 * @param curPage 第幾頁 * @param rowsPerPage 每頁多少行 * @return 返回分頁SQL語句 */ public String getPageMySQL(String sql, int curPage, int rowsPerPage){ String pageSql = sql+" limit "+ (curPage-1)*rowsPerPage+","+rowsPerPage; return pageSql; } /** * 生成Oracle分頁查詢語句 * @param sql 原始sql語句 * @return 返回分頁SQL語句 */ public String getOrclPageSql(String sql){ int begin = (curPage - 1) * rowsPerPage; int end = begin + rowsPerPage; StringBuffer pagingSelect = new StringBuffer(300); pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( "); pagingSelect.append(sql); pagingSelect.append(" ) row_ where rownum <= "+end+") where rownum_ > "+begin); return pagingSelect.toString(); } public List<T> getPageList() { return pageList; } public void setPageList(List<T> pageList) { this.pageList = pageList; } public int getTotalRows() { return totalRows; } public void setTotalRows(int totalRows) { this.totalRows = totalRows; } public int getTotalPages() { return totalPages; } public void setTotalPages(int totalPages) { this.totalPages = totalPages; } public int getCurPage() { return curPage; } public void setCurPage(int curPage) { this.curPage = curPage; } public int getPrePage() { return prePage; } public void setPrePage(int prePage) { this.prePage = prePage; } public int getNextPage() { return nextPage; } public void setNextPage(int nextPage) { this.nextPage = nextPage; } public int getRowsPerPage() { return rowsPerPage; } public void setRowsPerPage(int rowsPerPage) { this.rowsPerPage = rowsPerPage; } }
(5)定義SQL語句的經常用法工具類 package com.jkitn.jkits.util; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 說明:自己主動生成物件的增刪改查SQL語句的通用方法工具類 * @author xdweleven * @version 1.0 */ public class SQLUtil { /** * 自己主動生成插入指定物件的SQL語句,不包括物件屬性的值為空的欄位 * @param obj 待生成插入SQL語句的物件 * @param tableName 待插入語句相應的資料庫表的名稱 * @return 返回一個包括SQL語句、SQL語句引數值及引數值型別的Map物件 */ public static Map<String, Object> generateInsertExceptNull(Object obj, String tableName) { StringBuffer columnStrBuf = new StringBuffer(); // 記錄資料表的欄位名稱 StringBuffer paramStrBuf = new StringBuffer(); // 記錄SQL語句相應插入的佔位符 List<Object> paramValues = new ArrayList<Object>(); // 記錄物件引數值 List<Integer> paramsType = new ArrayList<Integer>(); // 記錄引數值型別 // 查詢待插入物件的屬性值不為空的屬性名稱 List<Object> fieldList = ReflectionUtil.getNotNullField(obj); try { for (int i = 0; i < fieldList.size(); i++) { Field field = (Field) fieldList.get(i); field.setAccessible(true); // 記錄物件屬性名稱 columnStrBuf.append(field.getName()); if (i != fieldList.size() - 1) { columnStrBuf.append(","); } // 記錄插入SQL語句的引數佔位符 if("class java.util.Date".equals(field.getType().toString()) && field.get(obj) != null){ String timeStr = DateUtil.formatDate((Date)field.get(obj), "yyyy-MM-dd HH:mm:ss"); paramStrBuf.append("to_date(?, 'yyyy-MM-dd HH24:mi:ss')"); paramValues.add(timeStr); // 記錄物件屬性的資料型別 paramsType.add(getOrclDataType(field.getType().toString())); }else{ paramStrBuf.append("?"); paramValues.add(field.get(obj)); // 記錄物件屬性的資料型別 paramsType.add(getOrclDataType(field.getType().toString())); } if (i != fieldList.size() - 1) { paramStrBuf.append(","); } } } catch (Exception e) { throw new RuntimeException(e); } // 生成插入操作的SQL語句 StringBuffer sb = new StringBuffer(); sb.append("insert into "); sb.append(tableName); sb.append(" ("); sb.append(columnStrBuf); sb.append(") "); sb.append("values"); sb.append(" ("); sb.append(paramStrBuf); sb.append(")"); // 將生成的SQL語句、SQL語句引數值及各引數值的資料型別用map儲存並返回 Map<String, Object> sqlMap = new HashMap<String, Object>(); sqlMap.put("sql", sb.toString()); sqlMap.put("paramsValues", paramValues.toArray()); sqlMap.put("paramsTypes", paramsType.toArray()); return sqlMap; } /** * 自己主動生成插入指定物件的SQL語句,包括物件屬性的值為空的欄位,不包括自增長主鍵,若不存在,呼叫時直接置為null. * @param obj 待生成插入SQL語句的物件 * @param tableName 待插入語句相應的資料庫表的名稱 * @param keyColumn 資料表主鍵名稱 * @return 返回一個包括SQL語句、SQL語句引數值及引數值型別的Map物件 * @throws IllegalAccessException * @throws IllegalArgumentException */ public static Map<String, Object> generateInsertWithNull(Object obj, String tableName, String keyColumn) throws IllegalArgumentException, IllegalAccessException { StringBuffer columnStrBuf = new StringBuffer(); StringBuffer paramStrBuf = new StringBuffer(); // 記錄SQL語句相應插入的佔位符 List<Object> columnNameList = new ArrayList<Object>(); // 記錄資料表的欄位名稱 List<Object> paramValues = new ArrayList<Object>(); // 記錄物件引數值 List<Integer> paramsType = new ArrayList<Integer>(); // 記錄引數值型別 Field[] fields = obj.getClass().getDeclaredFields(); for(int i = 0; i < fields.length; i++){ fields[i].setAccessible(true); // 記錄物件屬性名稱 if(!fields[i].getName().equalsIgnoreCase(keyColumn)){ // 非主鍵列記錄插入SQL語句的引數佔位符 columnStrBuf.append(fields[i].getName()); columnNameList.add(fields[i].getName()); if (i != fields.length - 1) { columnStrBuf.append(","); } if("class java.util.Date".equals(fields[i].getType().toString()) && fields[i].get(obj) != null){ String timeStr = DateUtil.formatDate((Date)fields[i].get(obj), "yyyy-MM-dd HH:mm:ss"); paramStrBuf.append("to_date(? , 'yyyy-MM-dd HH24:mi:ss')"); paramValues.add(timeStr); // 記錄物件屬性的資料型別 paramsType.add(getOrclDataType(fields[i].getType().toString())); }else{ paramStrBuf.append("?"); paramValues.add(fields[i].get(obj)); // 記錄物件屬性的資料型別 paramsType.add(getOrclDataType(fields[i].getType().toString())); } if (i != fields.length - 1) { paramStrBuf.append(","); } } } // 生成插入操作的SQL語句 StringBuffer sb = new StringBuffer(); sb.append("insert into "); sb.append(tableName); sb.append(" ("); sb.append(columnStrBuf); sb.append(") "); sb.append("values"); sb.append(" ("); sb.append(paramStrBuf); sb.append(")"); // 將生成的SQL語句、SQL語句的列名稱用map儲存並返回 Map<String, Object> sqlMap = new HashMap<String, Object>(); /* System.out.println(sb.toString()); System.out.println(columnNameList.toString()); System.out.println(paramValues.toString()); System.out.println(paramsType.toString()); */ sqlMap.put("sql", sb.toString()); sqlMap.put("columnNameList", columnNameList.toArray()); sqlMap.put("paramsValues", paramValues.toArray()); sqlMap.put("paramsTypes", paramsType.toArray()); return sqlMap; } /** * 自己主動生成更新指定物件的SQL語句 * @param obj 待生成更新SQL語句的物件 * @param tableName 待更新語句相應的資料庫表的名稱 * @param keyColumn 待更新記錄的限定欄位 * @return 返回一個包括SQL語句及引數值的陣列 */ public static Object[] generateUpdate(Object obj, String tableName, String keyColumn) { StringBuffer columnSB = new StringBuffer(); List<Object> params = new ArrayList<Object>(); Object keyValue = null; // 獲取屬性值不為空的資料表字段名稱 List<Object> fieldList = ReflectionUtil.getNotNullField(obj); try { for (int i = 0; i < fieldList.size(); i++) { Field field = (Field) fieldList.get(i); field.setAccessible(true); if (field.getName().equalsIgnoreCase(keyColumn)) { keyValue = field.get(obj); } else { columnSB.append(field.getName()); if("class java.util.Date".equals(field.getType().toString()) && field.get(obj) != null){ String timeStr = DateUtil.formatDate((Date)field.get(obj), "yyyy-MM-dd HH:mm:ss"); columnSB.append("=to_date(?, 'yyyy-MM-dd HH24:mi:ss')"); params.add(timeStr); }else{ columnSB.append("=?"); params.add(field.get(obj)); } if (i != fieldList.size() - 1) { columnSB.append(","); } } } } catch (Exception e) { throw new RuntimeException(e); } if (keyValue == null) { throw new IllegalArgumentException("資料表 [" + tableName+ "] 中的欄位'"+keyColumn+"'的值不能為空."); }else{ params.add(keyValue); } StringBuffer sb = new StringBuffer(); sb.append("update "); sb.append(tableName); sb.append(" set "); if(columnSB.length() >= 0){ sb.append(columnSB); }else{ sb.append(keyColumn); sb.append("=? "); params.add(keyValue); } sb.append(" where "); sb.append(keyColumn); sb.append("=? "); return new Object[] { sb.toString(), params.toArray() }; } /** * 返回java資料型別相應的Oracle資料庫的資料型別值 * @param javaType java資料型別 * @return 返回Oracle資料表的欄位資料型別 */ public static int getOrclDataType(String javaType){ if("class java.lang.String".equals(javaType)){ return java.sql.Types.VARCHAR; }else if("class java.lang.Integer".equals(javaType) || "int".equals(javaType)){ return java.sql.Types.INTEGER; }else if("class java.lang.Double".equals(javaType) || "double".equals(javaType)){ return java.sql.Types.DOUBLE; }else if("class java.lang.Float".equals(javaType) || "float".equals(javaType)){ return java.sql.Types.FLOAT; }else if("char".equals(javaType)){ return java.sql.Types.CHAR; }else if("class java.lang.Long".equals(javaType) || "long".equals(javaType)){ return java.sql.Types.NUMERIC; }else if("class java.util.Date".equals(javaType)){ return java.sql.Types.DATE; }else{ return java.sql.Types.VARCHAR; } } /** * 生成SQL語句中的where子句及where子句中引數值 * @param obj where條件子句的物件 * @return 返回條件不為空的where子句 * @throws Exception * @throws */ public static Map<String, Object> generateWhereStr(Object obj) throws Exception{ StringBuffer whereStrBuf = new StringBuffer(); // where子句 List<Object> whereParamValues = new ArrayList<Object>(); // where子句中的引數值 whereStrBuf.append(" where 1 = 1 "); if(obj != null){ Field[] fields = obj.getClass().getDeclaredFields(); for(int i = 0; i < fields.length; i++){ fields[i].setAccessible(true); Object columnName = fields[i].get(obj); if(columnName != null && !"".equals(columnName)){ whereStrBuf.append(" and "); whereStrBuf.append(fields[i].getName()); whereStrBuf.append("=?"); whereParamValues.add(columnName); } } } Map<String, Object> whereMap = new HashMap<String, Object>(); /* System.out.println(whereStrBuf.toString()); System.out.println(whereParamValues); */ whereMap.put("whereStr", whereStrBuf.toString()); whereMap.put("whereParamValues", whereParamValues.toArray()); return whereMap; } }
(6)擴充套件JAVA物件的反射工具類 package com.jkitn.jkits.util; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; /** * 說明:擴充套件JAVA物件的反射機制 * @author xdweleven * @version 1.0 */ public class ReflectionUtil { /** * 設定物件的指定屬性名稱的屬性值 * @param obj 待設定的物件 * @param fieldName 物件屬性名稱 * @param value 屬性值 */ public static void setFieldValue(Object obj, String fieldName, Object value) { Class<? extends Object> c = obj.getClass(); try { Field field = null; Field[] fields = c.getDeclaredFields(); for(int i = 0; i < fields.length; i++){ String fieldNameTemp = fields[i].getName(); if(fieldNameTemp.equalsIgnoreCase(fieldName)){ field = c.getDeclaredField(fieldNameTemp); field.setAccessible(true); field.set(obj, value); return; } } } catch (Exception e) { throw new RuntimeException(e); } } /** * 獲取物件的指定屬性名稱的屬性值 * @param obj 待設定的物件 * @param fieldName 物件屬性名稱 */ public static Object getFieldValue(Object obj, String fieldName) { Class<? extends Object> c = obj.getClass(); Field[] fields = c.getDeclaredFields(); try { for(int i = 0; i < fields.length; i++){ if(fields[i].getName().equalsIgnoreCase(fieldName)){ fields[i].setAccessible(true); return fields[i].get(obj); } } } catch (Exception e) { throw new RuntimeException(e); } return null; } /** * 獲取物件的屬性值不為空的屬性名稱 * @param obj 待獲取的物件 * @return 返回屬性值不為空的物件的屬性名稱列表 */ public static List<Object> getNotNullField(Object obj) { Class<? extends Object> c = obj.getClass(); List<Object> list = new ArrayList<Object>(); try { Field[] fields = c.getDeclaredFields(); for(int i = 0; i < fields.length; i++){ fields[i].setAccessible(true); if(fields[i].get(obj) != null){ list.add(fields[i]); } } } catch (Exception e) { throw new RuntimeException(e); } return list; } } (7)定義實現資料庫的CRUD基本操作BaseDao package com.jkitn.jkits.dao.common; import java.io.Serializable; import java.sql.ResultSet; import java.util.List; import java.util.Map; import com.jkitn.jkits.common.DBConn; import com.jkitn.jkits.common.PageBean; import com.jkitn.jkits.util.ReflectionUtil; import com.jkitn.jkits.util.SQLUtil; /** * 說明:封裝實現資料庫的CRUD相關的底層操作。 * @author xdweleven * @version 1.0 */ public class BaseDao{ // 獲取資料庫連結例項 private DBConn dbconn = new DBConn(); /** 資料庫表的字首 */ public static final String TB_PREFIX = "tb_jkit_"; /** 資料庫表的查詢字首 */ public static final String SELECT_TB_PREFIX = "select * from tb_jkit_"; /** 升序排列 */ public static final String ASC = "asc"; /** 降序排列 */ public static final String DESC = "desc"; /** * 依據ID查詢物件 * @param classType 物件型別 * @param columnName 編號欄位名稱 * @param id 物件編號 * @return 返回實體物件 */ public <T> T queryById(Class<T> classType, String columnName, Serializable id) throws Exception{ StringBuffer sqlBuffer = new StringBuffer(); sqlBuffer.append(SELECT_TB_PREFIX); sqlBuffer.append(this.toLowerCaseFirstOne(classType.getSimpleName())); sqlBuffer.append(" where "); sqlBuffer.append(columnName); sqlBuffer.append(" = ? "); this.showSQL(sqlBuffer.toString()); return dbconn.execQuery(sqlBuffer.toString(), new RowMapper<T>(classType), new Object[]{id}).get(0); } /** * 查詢全部指定class型別的物件資訊 * @param classType 物件型別 * @return 返回實體物件列表 */ public <T> List<T> queryAll(Class<T> classType) throws Exception{ String sql = SELECT_TB_PREFIX + this.toLowerCaseFirstOne(classType.getSimpleName()); this.showSQL(sql); return dbconn.execQuery(sql, new RowMapper<T>(classType)); } /** * 查詢指定物件型別的物件資訊,並依照指定的排序欄位進行升序或降序排序 * @param classType 物件型別 * @param orderColumn 排序欄位 * @param ascOrDesc 降序或升序:asc表示升序。desc表示降序 * @return 返回實體物件列表 */ public <T> List<T> queryAllWithOrder(Class<T> classType, String orderColumn, String ascOrDesc) throws Exception{ StringBuffer sqlBuffer = new StringBuffer(); sqlBuffer.append(SELECT_TB_PREFIX); sqlBuffer.append(this.toLowerCaseFirstOne(classType.getSimpleName())); sqlBuffer.append(" order by "); sqlBuffer.append(orderColumn); sqlBuffer.append(" "); sqlBuffer.append(ascOrDesc); this.showSQL(sqlBuffer.toString()); return dbconn.execQuery(sqlBuffer.toString(), new RowMapper<T>(classType)); } /** * 查詢指定SQL語句的物件資訊列表 * @param sql 查詢語句 * @param classType 物件型別 * @param params SQL語句引數 * @return 返回實體物件列表 */ public <T> List<T> query(String sql, Class<T> classType, Object... params) throws Exception{ this.showSQL(sql); return dbconn.execQuery(sql, new RowMapper<T>(classType), params); } /** * 查詢指定SQL語句的物件資訊列表 * @param sql 查詢語句 * @param classType 物件型別 * @param params SQL語句引數 * @return 返回實體物件列表 */ public <T> T queryForObj(String sql, Class<T> classType, Object... params) throws Exception{ this.showSQL(sql); return dbconn.execQuery(sql, new RowMapper<T>(classType), params).get(0); } /** * 分頁查詢實體物件列表資訊 * @param sql 原始的SQL語句 * @param classType 物件型別 * @param curPage 當前頁碼 * @param rowsPerPage 每頁顯示的記錄數 * @param params SQL語句引數 * @return 返回當前頁碼的分頁物件 */ public <T> PageBean<T> queryByPage(String sql, Class<T> classType, int curPage, int rowsPerPage, Object... params) throws Exception{ // 獲取記錄總數 int totalRows = this.getTotalRows(sql, params); PageBean<T> pageBean = new PageBean<T>(); pageBean.setCurPage(curPage); // 設定當前頁碼 pageBean.initPageBean(totalRows, rowsPerPage); // 初始化分頁物件的相關屬性 // 生成當前分頁查詢語句(MySql) String pageSql = pageBean.getPageMySQL(sql, curPage, rowsPerPage); this.showSQL(pageSql); // 執行查詢操作 pageBean.setPageList(dbconn.execQuery(sql, new RowMapper<T>(classType), params)); return pageBean; } /** * 儲存物件到資料庫中,若資料庫中的使用者表有自增序列,則須要指出表中自增列的欄位名稱,另外, * 資料庫中相應的自增序列的名稱需按例如以下格式取名:class名稱_自增列欄位名稱_SEQ, * 比如使用者的class為Users,自增序列欄位名稱為id,則資料庫中的自增序列的名稱取名為USERS_ID_SEQ. * @param obj 實體物件 * @param sequenceKeyColumn 資料表自增序列的欄位名稱,若不存在。則置為null。 * @return 返回被更新的記錄數 * @throws IllegalAccessException * @throws IllegalArgumentException */ public <T> int insert(T obj, String sequenceKeyColumn) throws Exception{ String tableName = TB_PREFIX + this.toLowerCaseFirstOne(obj.getClass().getSimpleName()); // 自己主動生成物件的無自增序列插入SQL語句及其相關插入的引數值和型別 Map<String, Object> sqlMap = SQLUtil.generateInsertWithNull(obj, tableName, sequenceKeyColumn); String sql = sqlMap.get("sql").toString(); // SQL語句 Object[] paramsValues = (Object[])sqlMap.get("paramsValues"); // SQL語句的引數值 // int[] paramsTypes = this.parseArrayToInt((Object[])sqlMap.get("paramsTypes")); // 引數值型別 this.showSQL(sql); return dbconn.execUpdate(sql, paramsValues); } /** * 更新物件 * @param obj 待更新的實體物件 * @param keyColumn 更新物件的限定條件欄位名稱 * @return 返回被更新的記錄數 */ public <T> int update(T obj, String keyColumn) throws Exception{ String tableName = TB_PREFIX + this.toLowerCaseFirstOne(obj.getClass().getSimpleName()); // 自己主動生成物件的更新操作的SQL語句及其引數值 Object[] updateSql = SQLUtil.generateUpdate(obj, tableName, keyColumn); this.showSQL(updateSql[0].toString()); return dbconn.execUpdate(updateSql[0].toString(), (Object[])updateSql[1]); } /** * 刪除物件 * @param obj 待更新的實體物件 * @param keyColumn 刪除的限定條件欄位 * @return 返回被刪除的記錄數 */ public <T> int delete(T obj, String keyColumn) throws Exception{ // 獲取限定條件的值 Object keyValue = ReflectionUtil.getFieldValue(obj, keyColumn); if(keyValue == null){ throw new RuntimeException("["+obj.getClass()+"]中不存在屬性'"+keyColumn+"'或屬性值為空."); } StringBuffer sqlBuffer = new StringBuffer(); sqlBuffer.append("delete from "); sqlBuffer.append(TB_PREFIX); sqlBuffer.append(this.toLowerCaseFirstOne(obj.getClass().getSimpleName())); sqlBuffer.append(" where "); sqlBuffer.append(keyColumn); sqlBuffer.append(" = ? "); this.showSQL(sqlBuffer.toString()); return dbconn.execUpdate(sqlBuffer.toString(), keyValue.toString()); } /** * 刪除指定編號的實體物件 * @param classType 物件型別 * @param keyColumn ID相應的資料表列名稱 * @param id 實體物件編號 * @return 返回刪除的記錄數 */ public <T> int deleteById(Class<T> classType, String keyColumn, Serializable id) throws Exception{ StringBuffer sqlBuffer = new StringBuffer(); sqlBuffer.append("delete from "); sqlBuffer.append(TB_PREFIX); sqlBuffer.append(this.toLowerCaseFirstOne(classType.getSimpleName())); sqlBuffer.append(" where "); sqlBuffer.append(keyColumn); sqlBuffer.append(" = ? "); this.showSQL(sqlBuffer.toString()); return dbconn.execUpdate(sqlBuffer.toString(), id); } /** * 批量刪除指定編號的實體物件 * @param classType 物件型別 * @param idColumnName 編號欄位名稱 * @param ids 待刪除物件的編號陣列 */ public <T> int deleteByIds(Class<T> classType, String idColumnName, Serializable[] ids) throws Exception{ StringBuffer sqlBuffer = new StringBuffer(); sqlBuffer.append("delete from "); sqlBuffer.append(TB_PREFIX); sqlBuffer.append(this.toLowerCaseFirstOne(classType.getSimpleName())); sqlBuffer.append(" where "); sqlBuffer.append(idColumnName); sqlBuffer.append(" = ? "); this.showSQL(sqlBuffer.toString()); int rowNums = 0; // 刪除的記錄數 for(int i = 0; i < ids.length; i++){ rowNums += this.deleteById(classType, idColumnName, ids[i]); } return rowNums; } /** * 更新操作 * @param sql 刪除操作的SQL語句 * @param params SQL語句中的引數值 * @return 返回刪除的記錄數 */ public int update(String sql, Object... params) throws Exception{ this.showSQL(sql); return dbconn.execUpdate(sql, params); } /** * 批量更新物件 * @param objs 待更新的實體物件列表 * @param keyColumn 主鍵欄位名稱 */ public <T> int batchUpdate(List<T> objs, String keyColumn) throws Exception{ if(objs == null || objs.isEmpty()){ return 0; } int updateNum = 0; // 自己主動生成物件的更新操作的SQL語句及其引數值 for(int i = 0; i < objs.size(); i++){ T obj = objs.get(i); updateNum += this.update(obj, keyColumn); } return updateNum; } /** * 批量插入物件 * @param objs 待新增的實體物件列表 * @param keyColumn 資料表主鍵列名稱 * @throws IllegalAccessException * @throws IllegalArgumentException */ public <T> int batchInsert(List<T> objs, String keyColumn) throws Exception { if(objs == null || objs.isEmpty()){ return 0; } int updateNum = 0; // 自己主動生成物件的更新操作的SQL語句及其引數值 for(int i = 0; i < objs.size(); i++){ T obj = objs.get(i); updateNum += this.insert(obj, keyColumn); } return updateNum; } /** * 統計指定統計數量的SQL語句 * @param sql 待執行的SQL語句 * @param params SQL語句引數值 * @return 返回記錄總數 * @throws Exception */ public int getTotalRows(String sql, Object... params) throws Exception{ String totalRowsSql = "select count(*) totalRows from ( "+sql+" )"; this.showSQL(totalRowsSql); ResultSet rs = dbconn.queryForResultSet(totalRowsSql, params); while(rs.next()){ return rs.getInt("totalRows"); } return 0; } /** * 刪除操作 * @param sql 刪除操作的SQL語句 * @param params SQL語句中的引數值 * @return 返回刪除的記錄數 */ public int delete(String sql, Object... params) throws Exception{ this.showSQL(sql); return dbconn.execUpdate(sql, params); } /** * 獲取下一個指定自增序列的值(MySql) * @param classType 物件型別 * @param seqColName 自增欄位名稱 * @return 返回指定表的主鍵自增序列的最新值 */ public <T> int getNextAutoIncrementVal(Class<T> classType, String seqColName) throws Exception{ StringBuffer sqlBuf = new StringBuffer(); sqlBuf.append("select max("); sqlBuf.append(seqColName); sqlBuf.append(")+1 nextId from "); sqlBuf.append(TB_PREFIX); sqlBuf.append(this.toLowerCaseFirstOne(classType.getSimpleName())); this.showSQL(sqlBuf.toString()); ResultSet rs = dbconn.queryForResultSet(sqlBuf.toString()); if(rs.next()){ return rs.getInt("nextId"); }else{ return 0; } } /** * 首字母轉小寫 * @param str 待轉換的字元創 * @return 返回首字母小寫後的字串 */ public String toLowerCaseFirstOne(String str){ if(Character.isLowerCase(str.charAt(0))){ return str; }else{ return (new StringBuilder()).append(Character.toLowerCase(str.charAt(0))). append(str.substring(1)).toString(); } } /** * 首字母轉大寫 * @param str 待轉換的字串 * @return 返回首字母大寫的字串 */ public String toUpperCaseFirstOne(String str){ if(Character.isUpperCase(str.charAt(0))){ return str; }else{ return (new StringBuilder()).append(Character.toUpperCase(str.charAt(0))). append(str.substring(1)).toString(); } } /** * 列印SQL語句 * @param sql */ public void showSQL(String sql){ System.out.println(sql); } }