利用java反射技术完成数据库表和实体类的映射关系,会遇到一些很常见的问题,实体类中有的字段数据库没有,或者数据库有的字段,实体类没有等到...该如何解决呢?
大概思路如下:
建立表与对应实体类的一个缓存集合,缓存实体类中跟表有映射关系的字段,用到时直接查询即可,下面给出部分代码:
//实体类中能与数据库对应起来的字段集合
private static Map<String, Map<String, Field>> databaseFieldsMap = new ConcurrentHashMap<String, Map<String, Field>>();
/***
* 缓存中的 数据库和实体类具有映射关系的field 用于反射查询 和实体对象的插入
* @param database 数据库名称
* @param cls 实体类class
* @return
*/
public static Map<String, Field> getTableFields(String database, Class<?> cls){
String key = database + "_" + cls.getSimpleName();
//当前类的对应字段信息
Map<String, Field> tableFields = databaseFieldsMap.get(key);
if(tableFields == null){
synchronized (SQLParamHelper.class) {
tableFields = databaseFieldsMap.get(key);
if(tableFields != null){
return tableFields;
}
Field[] fields = cls.getDeclaredFields();
Map<String, String> columnMap = getColumnMap(database, cls);
if(columnMap != null){
List<Field> lists = new ArrayList<Field>();
tableFields = new LinkedHashMap<String, Field>();
for(Field f : fields){
BeanField bf = f.getAnnotation(BeanField.class);
if(bf != null && !bf.persistence()){
continue;
}
if(Modifier.isStatic(f.getModifiers())){
continue;
}
//数据库中是否有当前字段 不区分大小写
if(columnMap.containsKey(f.getName().toLowerCase())){
lists.add(f);
tableFields.put(f.getName(), f);
}
}
databaseFieldsMap.put(key, tableFields);
}
}
}
return tableFields;
}
/***
* 获取表中的列 转换为 hashMap保存
* @param database
* @param cls
* @return
*/
private static Map<String, String> getColumnMap(String database, Class<?> cls){
//获取数据库连接
Connection conn = Data.getConnection(database);
Map<String, String> columnMap = new HashMap<String, String>();
ResultSet colRet = null;
try {
String tableName = getTableName(cls);
DatabaseMetaData metaData = conn.getMetaData();
ResultSet rsResult = metaData.getTables(null, "%", tableName, new String[]{"TABLE"});
if(rsResult!=null){
if(metaData != null){
colRet = metaData.getColumns(null,"%", tableName,"%");
while(colRet.next()) {
String columnName = colRet.getString("COLUMN_NAME");
String columnType = colRet.getString("TYPE_NAME");
// int datasize = colRet.getInt("COLUMN_SIZE");
// int digits = colRet.getInt("DECIMAL_DIGITS");
// int nullable = colRet.getInt("NULLABLE");
// System.out.println(columnName+" "+columnType+" "+datasize+" "+digits+" "+ nullable);
columnMap.put(columnName.toLowerCase(), columnType);
}
}
}
} catch (SQLException e) {
e.printStackTrace();
return null;
} finally {
if(colRet != null){
try {
colRet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return columnMap;
}
public static String getTableName(Class<?> cls){
String tableName = cls.getSimpleName();
AnnoBean annoBean = cls.getDeclaredAnnotation(AnnoBean.class);
if(annoBean != null && annoBean.tableName() != null){
tableName = annoBean.tableName();
}
return tableName;
}