我的目的是实现下Hibernate中增删改查、缓存的核心功能。虽然基本功能实现了,但可能还有好多Bug,欢迎点评拍砖,没准能在一片谩骂声中取得意想不到的进步,:)
// DatabaseAccess.java
1 package com.dsp.core; 2 3 import java.io.IOException; 4 import java.util.*; 5 6 /** 7 * 数据库访问操作类 8 * @author dsp 9 */ 10 public class DatabaseAccess { 11 // 数据库辅助帮助类实例 12 private DatabaseHelper databaseHelper = new DatabaseHelper(); 13 // DatabaseAccess类的泛型帮助类实例 14 private GenericityHelper genericityHelper = new GenericityHelper(); 15 16 /** 17 * 向数据库添加object 18 * @param object 待添加的对象 19 * @return 若成功向数据库添加object,则返回数据库中object对应记录的id号,否则,返回-1 20 */ 21 @SuppressWarnings("unchecked") 22 public synchronized int add(Object object) { 23 // object为空 24 if(null == object) 25 return -1; 26 27 List<String> columns = genericityHelper.getAllFieldNames(object); 28 Map<String, Object> columnToValues = genericityHelper.getFieldValues(columns, object); 29 30 /* 31 * 拼接带占位符的SQL语句 32 */ 33 String className = genericityHelper.getClassName(object).toLowerCase(); 34 String sql_0 = "insert into " + className + "("; 35 for(int index = 0; index < columns.size(); ++index) { 36 sql_0 += columns.get(index) + ","; 37 } 38 String sql_1 = sql_0.substring(0, sql_0.length() - 1) + ") values("; 39 // 设置占位符 40 for(int index = 0; index < columns.size(); ++index) { 41 sql_1 += "?,"; 42 } 43 String sql_2 = sql_1.substring(0, sql_1.length() - 1); 44 sql_2 += ");"; 45 46 /* 47 * 设置相应参数 48 */ 49 List<Object> params = new LinkedList<Object>(); 50 for(int index = 0; index < columns.size(); ++index) { 51 String fieldName = columns.get(index); 52 if("id".equals(fieldName)) 53 params.add(index, 0); 54 else 55 params.add(index, columnToValues.get(fieldName)); 56 } 57 58 // 执行插入 59 int result = databaseHelper.singleTableUpdate(sql_2, params, object.getClass()); 60 61 // 若插入成功 62 if(result > 0) { 63 String tableName = genericityHelper.getClassName(object); 64 List<Object> targetList = (List<Object>) databaseHelper.getCachedData(tableName, object.getClass()); 65 Object lastObject = targetList.get(targetList.size() - 1); 66 Object value = genericityHelper.getSpecifiedFieldValue("id", lastObject); 67 int id = Integer.parseInt(value.toString()); 68 return id; 69 } else { 70 return -1; 71 } 72 } 73 74 /** 75 * 从数据库中删除object 76 * @param object 待删除的对象 77 * @return 成功删除,返回true;否则返回false 78 */ 79 public synchronized boolean delete(Object object) { 80 // 对象为空 81 if(null == object) 82 return false; 83 84 /* 85 * 拼接带占位符的SQL语句 86 */ 87 String className = genericityHelper.getClassName(object); 88 List<String> columns = genericityHelper.getAllFieldNames(object); 89 Map<String, Object> columnToValues = genericityHelper.getFieldValues(columns, object); 90 String sql = "delete from " + className + " where id = " + columnToValues.get("id") + ";"; 91 92 // 执行删除操作 93 int result = databaseHelper.singleTableUpdate(sql, null, object.getClass()); 94 if(result > 0) 95 return true; 96 else 97 return false; 98 } 99 100 /** 101 * 更新数据库中德object对象 102 * @param object 要更新的对象 103 * @return 成功返回true,否则返回false 104 */ 105 public synchronized boolean update(Object object) { 106 // 对象为空 107 if(null == object) 108 return false; 109 110 String className = genericityHelper.getClassName(object); 111 String sql_0 = "update " + className + " set "; 112 113 List<Object> params = new ArrayList<Object>(); 114 List<String> columns = genericityHelper.getAllFieldNames(object); 115 Map<String, Object> columnToValues = genericityHelper.getFieldValues(columns, object); 116 117 /* 118 * 拼接带占位符的SQL语句 119 */ 120 for(int index = 0; index < columns.size(); ++index) { 121 String field = columns.get(index).toString(); 122 if(field.equals("id")) 123 continue; 124 sql_0 += field + "=?,"; 125 params.add(columnToValues.get(field)); 126 } 127 128 String sql_1 = sql_0.substring(0, sql_0.length() - 1) + " where id=?;"; 129 params.add(columnToValues.get("id")); 130 131 // 执行更新操作 132 int result = databaseHelper.singleTableUpdate(sql_1, params, object.getClass()); 133 if(result <= 0) 134 return false; 135 else 136 return true; 137 } 138 139 /** 140 * 从数据库中查询出所有的clazz记录,得到clazz记录的一份副本(深拷贝),使用时要求对应的Java Bean实现Serializable接口 141 * @param clazz 数据库表名映射的Java Bean反射实例 142 * @return 查询到的记录的链表 143 * @throws IOException 144 * @throws ClassNotFoundException 145 */ 146 @SuppressWarnings("unchecked") 147 public synchronized List<?> getAll(Class<?> clazz) { 148 List<?> resultsList = null; 149 try { 150 String className = genericityHelper.getClassName(clazz); 151 List<Object> tempResults = (List<Object>) databaseHelper.getCachedData(className, clazz); 152 resultsList = genericityHelper.deepClone(tempResults); 153 } catch (IOException e) { 154 e.printStackTrace(); 155 } catch (ClassNotFoundException e) { 156 e.printStackTrace(); 157 } 158 return resultsList; 159 } 160 161 }
// DatabaseHelper.java
1 package com.dsp.core; 2 3 import java.lang.reflect.Method; 4 import java.sql.*; 5 import java.util.ArrayList; 6 import java.util.HashMap; 7 import java.util.List; 8 import java.util.Map; 9 10 import com.dsp.util.Log; 11 12 /** 13 * 数据库JDBC操作辅助帮助类 14 * @author dsp 15 */ 16 public class DatabaseHelper { 17 // 已缓存了的数据链表 18 private static Map<String, List<Object>> cachedData = new HashMap<String, List<Object>>(); 19 20 // JDBC连接 21 private Connection connection; 22 // 预编译对象 23 private PreparedStatement pstmt; 24 25 /** 26 * 静态块,用来加载驱动 27 */ 28 static{ 29 try { 30 Class.forName(LoadDBConfigFile.getInstance().getProperty("driverClassName")); 31 } catch (ClassNotFoundException e) { 32 e.printStackTrace(); 33 Log.log.error(e.toString()); 34 } 35 } 36 37 /** 38 * 获取连接 39 */ 40 private Connection getConnection() { 41 try { 42 // 手动创建JDBC连接 43 connection = DriverManager.getConnection(LoadDBConfigFile.getInstance().getProperty("url"), LoadDBConfigFile.getInstance().getProperty("username"), LoadDBConfigFile.getInstance().getProperty("password")); 44 if(connection == null) { 45 System.out.println("Error!!!Failed to connect database!"); 46 System.exit(-1); 47 } 48 } catch (Exception e) { 49 Log.log.error(e.toString()); 50 } 51 return connection; 52 } 53 54 /** 55 * 关闭所有与JDBC相关的连接 56 * 顺序:先进后出 57 */ 58 private void closeAllConnections(Connection connection, PreparedStatement pstmt, ResultSet resultSet) { 59 if(pstmt != null) { 60 try { 61 pstmt.close(); 62 } catch (SQLException e) { 63 Log.log.error(e.toString()); 64 } 65 } 66 if(connection != null) { 67 try { 68 connection.close(); 69 } catch (SQLException e) { 70 Log.log.error(e.toString()); 71 } 72 } 73 } 74 75 /** 76 * 填充PreparedStatement对象的sql语句中的占位符 77 * @param pstmt PreparedStatement对象 78 * @param params 填充PreparedStatement对象中sql语句占位符的参数链表 79 * ####################################################################### 80 * 参数化查询(Parameterized Query 或 Parameterized Statement)是指在设计与 81 * 数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值, 82 * 这个方法目前已被视为最有效可预防SQL注入攻击(SQL Injection) 的攻击手法的防御方式。 83 */ 84 private void replacePlaceholder(PreparedStatement pstmt, List<Object> params) { 85 if((pstmt != null) && (params != null) && (params.size() > 0)) { 86 for(int index = 0; index < params.size(); ++index) { 87 Object obj = params.get(index); 88 try { 89 if(obj == null) { 90 // 若为null。//待优化处,减少拼接的SQL语句长度 91 pstmt.setNull(index + 1, Types.INTEGER); 92 } else if("java.util.Date".equals(obj.getClass().getName())) { 93 pstmt.setDate(index + 1, new java.sql.Date(((java.util.Date) params.get(index)).getTime())); 94 } else if("java.lang.Double".equals(obj.getClass().getName())) { 95 pstmt.setDouble(index + 1, (Double) params.get(index)); 96 } else if("java.lang.Integer".equals(obj.getClass().getName())) { 97 pstmt.setInt(index + 1, (Integer) params.get(index)); 98 } else if("java.lang.Boolean".equals(obj.getClass().getName())) { 99 pstmt.setBoolean(index + 1, (Boolean) params.get(index)); 100 } else if("javax.sql.rowset.serial.SerialBlob".equals(obj.getClass().getName())) { 101 pstmt.setBlob(index + 1, (Blob) params.get(index)); 102 } else { 103 pstmt.setString(index+1, (String)params.get(index)); 104 } 105 } catch (SQLException e) { 106 Log.log.error(e.toString()); 107 } 108 } 109 } 110 } 111 112 /** 113 * 打印输出SQL语句。 114 * 若成功,则是刚执行过的SQL语句; 115 * 失败则是致使数据库系统抛出异常的非法语句。 116 * @param pstmt 预编译SQL语句对象 117 */ 118 private void printExecutedSQL(PreparedStatement pstmt) { 119 String executedSQL = pstmt.toString(); 120 System.out.println("====>" + executedSQL); 121 } 122 123 /** 124 * 该表的数据是否已缓存 125 * @param tableName 表明 126 * @return 已缓存:true 否则返回 false 127 */ 128 private boolean isCached(String tableName) { 129 List<Object> tempList = cachedData.get(tableName); 130 if(tempList == null) { 131 return false; 132 } 133 return true; 134 } 135 136 /** 137 * 根据键名获取对应已缓存的数据 138 * @param classNameOrTableName 取数据用的键名 139 * @return 缓存的数据链表 140 */ 141 public List<?> getCachedData(String classNameOrTableName, Class<?> clazz) { 142 if(isCached(classNameOrTableName)) { 143 return cachedData.get(classNameOrTableName); 144 } else { 145 // 若数据不在缓存中,则向数据库发送查询请求 146 String sql = "select * from " + classNameOrTableName + ";"; 147 return this.singleTableQuery(sql, null, clazz); 148 } 149 } 150 151 /** 152 * 对单表进行更新操作 153 * @param sql 带占位符的SQL语句 154 * @param params 用户填充SQL语句中的占位符的参数 155 * @return 执行结果:>0 成功 <=0 失败 156 */ 157 public synchronized int singleTableUpdate(String sql, List<Object> params, Class<?> clazz) { 158 connection = getConnection(); 159 int result = 0; 160 try { 161 // 预编译对象 162 pstmt = connection.prepareStatement(sql); 163 replacePlaceholder(pstmt, params); 164 result = pstmt.executeUpdate(); 165 // 放在此处是出于打印的语句与数据库实际操作的顺序一致性 166 printExecutedSQL(pstmt); 167 168 // 更新缓存 169 String className = new GenericityHelper().getClassName(clazz); 170 String querySQL = "select * from " + className + ";"; 171 this.singleTableQuery(querySQL, null, clazz); 172 } catch (SQLException e) { 173 try { 174 // 出错则打印SQL语句并回滚 175 printExecutedSQL(pstmt); 176 connection.rollback(); 177 } catch (SQLException e1) { 178 e1.printStackTrace(); 179 } 180 // 记录异常 181 e.printStackTrace(); 182 Log.log.error(e.toString()); 183 } finally { 184 closeAllConnections(connection, pstmt, null); 185 } 186 return result; 187 } 188 189 /** 190 * 191 * @param sql 查询语句语句,可以含有占位符 192 * @param params 填充占位符的参数集 193 * @param clazz 泛型类型所对应的反射对象 194 * @param <T> 泛型:即你要得到的集合中存的对象的类型 195 * @return 存储查询到的所有对象链表 196 */ 197 @SuppressWarnings({ "unchecked" }) 198 private synchronized <T> List<Object> singleTableQuery(String sql, List<Object> params, Class<T> clazz) { 199 // 若clazz为空 200 if(null == clazz) { 201 return null; 202 } 203 204 /* 205 * 最新数据还未缓存,所以执行查询,检出数据库中的数据 206 */ 207 List<T> resultList = new ArrayList<T>(); 208 connection = getConnection(); 209 ResultSet resultSet = null; 210 211 try { 212 // 预编译SQL语句对象 213 pstmt = connection.prepareStatement(sql); 214 replacePlaceholder(pstmt, params); 215 resultSet = pstmt.executeQuery(); 216 217 ResultSetMetaData resultSetMetaData = resultSet.getMetaData(); 218 String[] columnNames = new String[resultSetMetaData.getColumnCount()]; 219 220 for(int index = 0; index < columnNames.length; ++index) { 221 columnNames[index] = resultSetMetaData.getColumnName(index + 1); 222 } 223 224 while(resultSet.next()) { 225 T temp = (T) clazz.newInstance(); 226 for(int index = 0; index < columnNames.length; ++index) { 227 String targetMethdName = "set" + columnNames[index]; 228 Method[] methods = clazz.getMethods(); 229 if((methods != null) && (methods.length > 0)) { 230 for(Method method : methods) { 231 String tempMethodName = method.getName(); 232 if(targetMethdName.equalsIgnoreCase(tempMethodName)) { 233 Object tempObject = resultSet.getObject(columnNames[index]); 234 if(tempObject != null) { 235 String columnTypeName = tempObject.getClass().getName(); 236 if("java.lang.Integer".equals(columnTypeName)) { 237 method.invoke(temp, resultSet.getInt(columnNames[index])); 238 } else if("java.sql.Date".equals(columnTypeName)) { 239 method.invoke(temp, resultSet.getDate(columnNames[index])); 240 } else if("java.lang.Double".equals(columnTypeName)) { 241 method.invoke(temp, resultSet.getDouble(columnNames[index])); 242 } else if("java.lang.Boolean".equals(columnTypeName)) { 243 method.invoke(temp, resultSet.getBoolean(columnNames[index])); 244 } else { 245 method.invoke(temp, resultSet.getString(columnNames[index])); 246 } 247 } 248 break; 249 } 250 } 251 } 252 } 253 resultList.add(temp); 254 } 255 } catch (Exception e) { 256 e.printStackTrace(); 257 Log.log.equals(e.toString()); 258 } finally { 259 printExecutedSQL(pstmt); 260 closeAllConnections(connection, pstmt, resultSet); 261 } 262 263 // 缓存最新数据 264 String tableName = new GenericityHelper().getClassName(clazz); 265 cachedData.remove(tableName); 266 cachedData.put(tableName, (List<Object>) resultList); 267 268 return (List<Object>) resultList; 269 } 270 271 }
// GenericityHelper.java
1 package com.dsp.core; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.IOException; 6 import java.io.ObjectInputStream; 7 import java.io.ObjectOutputStream; 8 import java.lang.reflect.Field; 9 import java.lang.reflect.InvocationTargetException; 10 import java.lang.reflect.Method; 11 import java.sql.Timestamp; 12 import java.util.ArrayList; 13 import java.util.HashMap; 14 import java.util.List; 15 import java.util.Map; 16 17 import com.dsp.util.Log; 18 19 /** 20 * DatabaseAccess类的辅助帮助类 21 * 声明: 22 * 本来这个类的所有方法完全可安置到DatabaseAccess类中,从数据耦合 23 * 这个层面上来讲,DatabaseAccess类有太多的数据处理需要此类中的方法; 24 * 但考虑到代码都放到一个类中就显得代码有点冗长了,可以适时调整代码位置。 25 * @author dsp 26 */ 27 public class GenericityHelper { 28 /** 29 * 获取对象object的简短类名 30 * @param object 待操作的对象 31 * @return object对象所对应的类名 32 */ 33 public String getClassName(Object object) { 34 Class<?> clazz = getReflectClass(object); 35 String classFullName = getClassFullName(clazz); 36 return classFullName.substring(classFullName.lastIndexOf(".") + 1).toLowerCase(); 37 } 38 39 /** 40 * 重载方法 41 * 获取对象object的简短类名 42 * @param clazz 反射类实例 43 * @return 反射类实例所对应的类名 44 */ 45 public String getClassName(Class<?> clazz) { 46 String classFullName = getClassFullName(clazz); 47 return classFullName.substring(classFullName.lastIndexOf(".") + 1).toLowerCase(); 48 } 49 50 /** 51 * 获取对象所有的的字段名 52 * @param object 操作的对象 53 * @return object所有的字段名 54 */ 55 public List<String> getAllFieldNames(Object object) { 56 Class<?> clazz = getReflectClass(object); 57 Field[] fields = clazz.getDeclaredFields(); 58 List<String> columns = new ArrayList<String>(); 59 for(int index = 0; index < fields.length; ++index) { 60 columns.add(index, fields[index].getName().toString()); 61 } 62 return columns; 63 } 64 65 /** 66 * 获取所有字段对应的值:键值对 67 * @param columns 所有的字段名 68 * @param object 值来源对象 69 * @return object所有的字段对应的值 70 */ 71 public Map<String, Object> getFieldValues(List<String> columns, Object object) { 72 Map<String, Object> columnToValues = new HashMap<String, Object>(); 73 for(int index = 0; index < columns.size(); ++index) { 74 String fieldName = columns.get(index).toString(); 75 columnToValues.put(fieldName, getSpecifiedFieldValue(fieldName, object)); 76 } 77 return columnToValues; 78 } 79 80 /** 81 * 根据类字段名获取该字段对应的值 82 * @param fieldName 字段名 83 * @param object 数据源对象 84 * @return object中fieldName字段对应的值 85 */ 86 public Object getSpecifiedFieldValue(String fieldName, Object object) { 87 List<String> methodNames = generateMethodNames(fieldName); 88 Method targetMethod = getExistedMethod(methodNames, getReflectClass(object)); 89 Object value = getValueBySpecifiedMethod(targetMethod, object); 90 return dataCastType(value); 91 } 92 93 /** 94 * 获取对象object的反射类实例 95 * @param object 操作对象 96 * @return object对象的反射类实例 97 */ 98 private Class<? extends Object> getReflectClass(Object object) { 99 return object.getClass(); 100 } 101 102 /** 103 * 获取反射类实例的类全名 104 * @param clazz 反射类实例 105 * @return clazz的类全名 106 */ 107 private String getClassFullName(Class<?> clazz) { 108 return clazz.getName(); 109 } 110 111 /** 112 * 获取object对象的指定函数返回的值 113 * @param targetMethod 指定的函数 114 * @param object 操作的对象 115 * @return object对象的targetMethod函数返回的值 116 */ 117 private Object getValueBySpecifiedMethod(Method targetMethod, Object object) { 118 Object value = null; 119 try { 120 value = targetMethod.invoke(object, new Object[] {}); 121 } catch (IllegalAccessException e) { 122 e.printStackTrace(); 123 Log.log.error(e.toString()); 124 } catch (InvocationTargetException e) { 125 e.printStackTrace(); 126 Log.log.error(e.toString()); 127 } 128 return value; 129 } 130 131 /** 132 * 数据转换 133 * @param value 待转换的值 134 * @return 转换后的值 135 */ 136 private Object dataCastType(Object value) { 137 if(value instanceof Timestamp) 138 value = Timestamp.valueOf(value.toString()); 139 return value; 140 } 141 142 /** 143 * 判断methodName是否是对象中存在的函数名 144 * @param methodName 待校验的可能的函数名 145 * @param clazz 反射类实例 146 * @return 若methodName是clazz中的函数名,返回true,否则返回false 147 */ 148 private boolean isExistedMethodName(String methodName, Class<?> clazz) { 149 Method[] methods = clazz.getMethods(); 150 for(Method method : methods) { 151 if(method.getName().equals(methodName)) 152 return true; 153 } 154 return false; 155 } 156 157 /** 158 * 根据可能的函数名字检索clazz对象存在的函数 159 * @param methodNames 函数名字链表 160 * @param clazz 反射类实例 161 * @return 在clazz对象中根据函数名字检索到的函数 162 */ 163 private Method getExistedMethod(List<String> methodNames, Class<?> clazz) { 164 for(String methodName : methodNames) { 165 if(isExistedMethodName(methodName, clazz)) { 166 try { 167 Method targetMethod = clazz.getMethod(methodName, new Class[] {}); 168 if(targetMethod != null) { 169 return targetMethod; 170 } 171 } catch (NoSuchMethodException | SecurityException e) { 172 e.printStackTrace(); 173 Log.log.error(e.toString()); 174 } 175 } 176 } 177 return null; 178 } 179 180 /** 181 * 根据字段名生成可能的目标函数名 182 * @param fieldName 字段名 183 * @return 根据fieldName生成的所有可能的目标函数名,将其存放在链表中 184 */ 185 private List<String> generateMethodNames(String fieldName) { 186 List<String> methodNames = new ArrayList<String>(); 187 String firstLetter = fieldName.substring(0, 1).toUpperCase(); 188 String postfix = firstLetter + fieldName.substring(1); 189 190 /* 191 * IDE自动生成的getter函数前缀不一定都是"get" 192 */ 193 // 方法是”getXyz()“ 194 String methodPrefixGet = "get" + postfix; 195 methodNames.add(methodPrefixGet); 196 // 方法名是“isXyz()” 197 String methodPrefixIs = "is" + postfix; 198 methodNames.add(methodPrefixIs); 199 200 return methodNames; 201 } 202 203 /** 204 * 深拷贝List<Object>,要求Object已实现Serializable接口 205 * @param sourceList 源List 206 * @return 源List的一份副本 207 * @throws IOException 208 * @throws ClassNotFoundException 209 */ 210 @SuppressWarnings("unchecked") 211 public List<Object> deepClone(List<Object> sourceList) throws IOException, ClassNotFoundException { 212 ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream(); 213 ObjectOutputStream objectOutStream = new ObjectOutputStream(byteOutStream); 214 objectOutStream.writeObject(sourceList); 215 216 ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutStream.toByteArray()); 217 ObjectInputStream objectInputStream =new ObjectInputStream(byteInputStream); 218 List<Object> destList = (List<Object>) objectInputStream.readObject(); 219 return destList; 220 } 221 222 }
// LoadDBConfigFile.java
1 package com.dsp.core; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.Properties; 6 7 import com.dsp.util.Log; 8 9 /** 10 * 加载数据库配置文件 11 * @author dsp 12 */ 13 public class LoadDBConfigFile extends Properties { 14 private static final long serialVersionUID = 1907772550710288554L; 15 16 private static LoadDBConfigFile instance = null; 17 18 /** 19 * 对外提供一个工厂方法 20 * @return LoadDBConfigFile的全局唯一实例 21 */ 22 public synchronized static LoadDBConfigFile getInstance() { 23 if(instance != null) { 24 return instance; 25 } else { 26 instance = new LoadDBConfigFile(); 27 return instance; 28 } 29 } 30 31 /** 32 * 单例模式的核心:构造方法私有化 33 */ 34 private LoadDBConfigFile() { 35 // db.properties文件保存有基本的配置信息 36 // 通过类的反射实例找到并加载classpath路径下的指定资源文件,并将其生成一个输入流; 37 InputStream inputStream = this.getClass().getResourceAsStream("/db.properties"); 38 try { 39 // 将输入流中的信息加载到类的当前对象中 40 this.load(inputStream); 41 } catch (IOException e) { 42 Log.log.error(e.toString()); 43 } finally { 44 try { 45 inputStream.close(); 46 } catch (IOException e) { 47 e.printStackTrace(); 48 Log.log.error(e.toString()); 49 } 50 } 51 } 52 53 }
// Log.java
1 package com.dsp.util; 2 3 import org.apache.log4j.Logger; 4 import org.apache.log4j.PropertyConfigurator; 5 6 public class Log { 7 8 public static Logger log; 9 10 static { 11 PropertyConfigurator.configure("/log4j.properties"); 12 log = Logger.getLogger(Log.class); 13 log.debug("debug"); 14 log.error("error"); 15 } 16 17 }
// db.properties
- driverClassName=com.mysql.jdbc.Driver
- url=jdbc:mysql://127.0.0.1:3306/retina
- username=root
- password=123456
// log4j.properties
- log4j.appender.stdout=org.apache.log4j.ConsoleAppender
- log4j.appender.stdout.Target=System.out
- log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
- log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %m%n
- log4j.appender.file=org.apache.log4j.FileAppender
- log4j.appender.file.File=retina.log
- log4j.appender.file.layout=org.apache.log4j.PatternLayout
- log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n
- log4j.rootLogger=WARN,stdout,file
// DatabaseAccessTester.java 测试代码
1 import com.dsp.bean.MovieType; 2 import com.dsp.core.DatabaseAccess; 3 import java.lang.reflect.InvocationTargetException; 4 import java.util.Date; 5 import java.util.List; 6 7 /** 8 * Created by dsp on 14-3-9. 9 */ 10 public class DataBaseAccessTester { 11 public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 12 // MovieType movieType = new MovieType(); 13 // movieType.setId(6); 14 // movieType.setName("101010"); 15 // new DatabaseAccess().add(movieType); 16 // 17 DatabaseAccess databaseAccess = new DatabaseAccess(); 18 // List<MovieType> movieTypes = (List<MovieType>) databaseAccess.getAll(MovieType.class); 19 // for(MovieType movieType_ : movieTypes) { 20 // System.out.println(movieType_); 21 // } 22 // 23 // System.out.println("#############################################################"); 24 // 25 // MovieType movieType_1 = new MovieType(); 26 // movieType_1.setId(8); 27 // movieType_1.setName("888"); 28 // new DatabaseAccess().update(movieType_1); 29 // 30 // System.out.println("#############################################################"); 31 // 32 // List<MovieType> movieTypes_1 = (List<MovieType>) databaseAccess.getAll(MovieType.class); 33 // for(MovieType movieType_2 : movieTypes_1) { 34 // System.out.println(movieType_2); 35 // } 36 // 37 // System.out.println("#############################################################"); 38 // System.out.println("#############################################################"); 39 // 40 // MovieType movieType_2 = new MovieType(); 41 // movieType_2.setId(9); 42 // movieType_2.setName("dsp"); 43 // new DatabaseAccess().update(movieType_2); 44 // 45 // System.out.println("#############################################################"); 46 47 // List<MovieType> movieTypes_22 = (List<MovieType>) databaseAccess.getAll(MovieType.class); 48 // movieTypes_22.remove(0); 49 // movieTypes_22.remove(3); 50 // movieTypes_22.add(new MovieType()); 51 // for(MovieType movieType_22 : movieTypes_22) { 52 // System.out.println(movieType_22); 53 // } 54 // 55 // System.out.println("###############################################################"); 56 // 57 // List<MovieType> movieTypeList_23 = (List<MovieType>) new DatabaseHelper().getCachedData("movietype", MovieType.class); 58 // for(MovieType movieType_22 : movieTypeList_23) { 59 // System.out.println(movieType_22); 60 // } 61 // 62 // System.out.println("#########################"); 63 // System.out.println(movieTypes_22 == movieTypeList_23); 64 65 // ################################################################################## 66 } 67 68 }
^_^ ~