Why
在写一些复杂的查询时,JPA已经不满足我的要求了,然后就使用了jdbcTemplate,但是会面临一个问题,查询结果集是List<Map<String,Object>>,还需转换到我对应的实体类,属性一个个拿出来再赋值实在太累,所以写一个工具类方便以后转换
How
首先看下我遇到的问题以及处理方案,方便大家理解。
- 数据库字段名是product_name 而实体类里面是productName
private static Pattern linePattern = Pattern.compile("_(\\w)");
private static Pattern humpPattern = Pattern.compile("[A-Z]");
/** 下划线转驼峰 */
public static String lineToHump(String str) {
str = str.toLowerCase();
Matcher matcher = linePattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString();
}
/** 驼峰转下划线 */
public static String humpToLine(String str) {
Matcher matcher = humpPattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
}
matcher.appendTail(sb);
return sb.toString();
}
- String 类型的值 map可以直接赋值到实体类,但是像Long,Date等类型的需要你处理,因为map接受到的数据都是string类型的(核心处理)
/**
* 将map集合中的数据转化为指定对象的同名属性中
*/
public static <T> T mapToBean(Map<String, Object> map,Class<T> clazz) throws Exception {
T bean = null;
try {
bean = clazz.newInstance();
for (Field field : getAllFields(clazz)) {
if (map.containsKey(humpToLine(field.getName()))) {
boolean flag = field.isAccessible();
field.setAccessible(true);
Object object = map.get(humpToLine(field.getName()));
if (object != null){
if(field.getType().isAssignableFrom(object.getClass())){
field.set(bean, object);
}else{
//判断属性类型 进行转换,map中存放的是Object对象需要转换 实体类中有多少类型就加多少类型,实体类属性用包装类;
if(field.getType().toString().contains("Long")){
field.set(bean, Long.parseLong(object.toString()));
}
//处理LocalDateTime类型
if(field.getType().toString().contains("LocalDateTime")){
field.set(bean, stringConvertLocalDateTime(object.toString()));
}
}
}
field.setAccessible(flag);
}
}
return bean;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return bean;
}
- 最后取对象属性时,getFields()并不能取到父类的属性,所以做了一个简单对父类属性的处理,但是有个缺点是只有一层父类,欢迎讨论好的解决方案
/**
* 获取自身和上一级父类属性
* @param clazz
* @param <T>
* @return
*/
public static <T> Field[] getAllFields(Class<T> clazz){
List<Field> fieldList = new ArrayList<>();
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
if(clazz.getSuperclass()!=null){
//写死的 取一层父类 TODO 没有好的解决方案
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getSuperclass().getDeclaredFields())));
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
最后
这样使用jdbcTemplate查询转对象就非常方便啦,又可以愉快的使用JPA开发项目了。