原文地址:Spring JdbcTemplate 查询结果集Map反向生成Java实体

以前写过一篇文章吐槽过Spring JdbcTemplate的queryForList方法(参见:http://blog.csdn.net/will_awoke/article/details/12617383),因为这个方法只支持单数据类型泛型实体,而想返回自定义实体时还得自己写callback方法,笔者不想在每个返回自定义实体的query方法中都去写callback处理返回的map,于是索性就自己造了个轮子,有点像hibernate的orm的赶脚。话说,现在用惯了SpringJDBC,反而又不喜欢hibernate了,感觉hibernate太重了,人就是这么奇怪。O(∩_∩)O~

回归正题,下面讲下造的这个轮子,轮子的应用场景如下:

1.已使用了 List<Map<String, Object>> org.springframework.jdbc.core.JdbcTemplate.queryForList(String sql, Object[] args, int[] argTypes) throws DataAccessException 方法,想将此方法返回的Map反向生成对应的实体Instance;

2.而你又不想在使用到上述方法的每处都override callback方法去处理map(和笔者一样懒,O(∩_∩)O~);

3.你的实体类字段和DBTable中的字段命名不一样,关于这一点下文会提到,其实,真正按着编程规范来的话,实体类是绝对不可能和DB中字段命名一样的。

如果你具备了上述应用场景,那么可以继续向下看轮子了。

我们知道jdbcTemplate.queryForList(sql, params, types)返回的是个List<Map<String,Object>>,如:{USER_ID=5438,LOGIN_NAME=admin,PASSWORD=admin123456},其中key是大写的。想根据map反向生成JavaBeanInstance,首先你得拥有一个实体类,下面是一个轮子中用到的Bean.java:

import java.io.Serializable;

import javax.persistence.Column;

import com.alibaba.fastjson.JSON;

/**
* 系统用户
*
* column注解配置与hibernate一致,不过只需要name属性,其他属性不再需要
* name属性值对应数据库中字段名称,忽略大小写
* 该注解用于map反向生成modelbean
* 另请参考:ReflectUtil.java
*
* @author will_awoke
* @version 2014-5-29
* @see SysUser
* @since
*/
public class SysUser implements Serializable
{ /**
* 序列号<br>
*/
private static final long serialVersionUID = 7931705053661707847L; @Column(name = "USER_ID")
private Long userId; @Column(name = "LOGIN_NAME")
private String loginName; @Column(name = "PASSWORD")
private String password; /**
* 构造器
*/
public SysUser()
{ } @Override
public String toString()
{
return JSON.toJSONString(this);
} //setter getter
public Long getUserId()
{
return userId;
} public void setUserId(Long userId)
{
this.userId = userId;
} public String getLoginName()
{
return loginName;
} public void setLoginName(String loginName)
{
this.loginName = loginName;
} public String getPassword()
{
return password;
} public void setPassword(String password)
{
this.password = password;
} }

实体类中使用了@Column注解,用于绑定实体field字段和DB中column字段,思想类似于Hibernate。

关于@Column 可以使用Hibernate提供的jar:

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>ejb3-persistence</artifactId>
<version>1.0.2.GA</version>
</dependency>

或者是自己可以手写个注解:

/**
* 注解映射
*
* @author will_awoke
* @version
* @see Column
* @since
*/
@Target(java.lang.annotation.ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column { String name() default ""; }

核心反射工具类如下:

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map; import javax.persistence.Column; import com.alibaba.fastjson.JSON;
import com.iss.rabc.bean.SysUser; /**
*
* @author will_awoke
* @version 2014-5-30
* @see ReflectUtil
* @since
*/
public class ReflectUtil
{ /**
* 将jdbcTemplate查询的map结果集 反射生成对应的bean
* @param clazz 意向反射的实体.clazz
* @param jdbcMapResult 查询结果集 key is UpperCase
* @return
* @see
*/
public static <T> T reflect(Class<T> clazz, Map<String, Object> jdbcMapResult)
{
//获得
Field[] fields = clazz.getDeclaredFields(); //存放field和column对应关系,该关系来自于实体类的 @Column配置
Map<String/*field name in modelBean*/, String/*column in db*/> fieldHasColumnAnnoMap = new LinkedHashMap<String, String>();
Annotation[] annotations = null;
for (Field field : fields)
{
annotations = field.getAnnotations();
for (Annotation an : annotations)
{
if (an instanceof Column)
{
Column column = (Column)an;
fieldHasColumnAnnoMap.put(field.getName(), column.name());
}
}
}
//存放field name 和 对应的来自map的该field的属性值,用于后续reflect成ModelBean
Map<String, Object> conCurrent = new LinkedHashMap<String, Object>();
for (Map.Entry<String, String> en : fieldHasColumnAnnoMap.entrySet())
{
//将column大写。因为jdbcMapResult key is UpperCase
String key = en.getValue().toUpperCase(); //获得map的该field的属性值
Object value = jdbcMapResult.get(key); //确保value有效性,防止JSON reflect时异常
if (value != null)
{
conCurrent.put(en.getKey(), jdbcMapResult.get(key));
}
}
//fastjson reflect to modelbean
return JSON.parseObject(JSON.toJSONString(conCurrent), clazz);
} /**
* test example
* @param args
* @throws Exception
* @see
*/
public static void main(String[] args)
throws Exception
{
//call reflect testing
Map<String, Object> jdbcMapResult = new HashMap<>();
jdbcMapResult.put("LOGIN_NAME", "reflect");
jdbcMapResult.put("PASSWORD", "reflect123456"); System.out.println(ReflectUtil.reflect(SysUser.class, jdbcMapResult));
}
}

工具类中,实现map的替换处理,然后利用fastjson将map反射成JavaBean即可,一如上述的场景条件3中提到,如果实体类字段和DBTable中的字段命名一样直接就可以用fastjson reflect成JavaBean,而就不需要这些轮子了。

应用层调用:

import static com.iss.util.ReflectUtil.reflect;

List<Map<String, Object>> mapList = userDao.queryNaviByUser(loginName);

List<SysMenu> meunList = new LinkedList<SysMenu>();
for (Map<String, Object> jdbcMapResult : mapList)
{
//利用工具类反向生成bean
meunList.add(reflect(SysMenu.class, jdbcMapResult));
}

Spring JdbcTemplate 查询结果集Map反向生成Java实体(转)的更多相关文章

  1. Spring JdbcTemplate 查询出的Map,是如何产生大小写忽略的Key的?(转)

    原文地址:Spring JdbcTemplate 查询出的Map,是如何产生大小写忽略的Key的? 原始讨论组:用Spring JdbcTemplate 查询出的Map,是如何产生大小写忽略的Key的 ...

  2. MyEclipse 利用反向功能生成Java 实体类

    1.Window -> Open Perspective -> MyEclipse Database Explorer 到DB Broswer界面 2.右键 -> New,新建一个数 ...

  3. MyEclipse 从数据库反向生成Hibernate实体类

    第一个大步骤 window-->open Perspective-->MyEclipse Java Persistence 进行了上面的 操作后会出现一个视图DB Brower:MyEcl ...

  4. MyEclipse反向生成Java代码 ,Reverse Engineering-->Java Source Folder-->没有提供任何条目

    在web项目名称上,手动执行一遍Add Hibernate Capabilities,然后再去DB Browser中进行反向生成pojo实体类和hbm.xml映射文件!,具体生成反向代码的配置如下图所 ...

  5. JDBCUtils,根据当前MySQL数据库下面的表生成java实体类

    自己简单写的JDBCUtils,可以根据当前数据库下面的表生成java实体类,代码萌新,请多多包涵. 初始化配置: //驱动程序名//不固定,根据驱动 static String driver = & ...

  6. 在线数据库表(sql语句)生成java实体类工具

    相信每个做java开发的读者,都接触过SQL建表语句,尤其是在项目开发初期,因为数据库是项目的基石. 在现代项目开发中,出现了许多ORM框架,通过简单的实体映射,即可实现与数据库的交互,然而我们最初设 ...

  7. Mysql逆向工程效率神器之使用IDE自动生成Java实体类

    Mysql逆向工程效率神器之使用IDE自动生成Java实体类 简介:实战使用IDE根据Mysql自动生成java pojo实体类 1.IDEA连接数据库 菜单View→Tool Windows→Dat ...

  8. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_2-6.Mysql逆向工程效率神器之使用IDE自动生成Java实体类

    笔记 6.Mysql逆向工程效率神器之使用IDE自动生成Java实体类     简介:实战使用IDE根据Mysql自动生成java pojo实体类                  1.IDEA连接数 ...

  9. [转] spring JdbcTemplate 查询,使用BeanPropertyRowMapper

    [From] http://blog.csdn.net/limenghua9112/article/details/45096437 应用: 使用Spring的JdbcTemplate查询数据库,获取 ...

随机推荐

  1. C++中set的用法

    set的特性是,所有元素都会根据元素的键值自动排序,set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值.set不允许两个元素有相同的键值. ...

  2. 【译】第38节---EF6-基于代码的配置

    原文:http://www.entityframeworktutorial.net/entityframework6/code-based-configuration.aspx EF6引入了基于代码的 ...

  3. 【译】第20节---数据注解-InverseProperty

    原文:http://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-co ...

  4. Linux命令去重统计排序

    利用Linux命令进行文本按行去重并按重复次数排序   linux命令行提供了非常强大的文本处理功能,组合利用linux命令能实现好多强大的功能.本文这里举例说明如何利用Linux命令行进行文本按行去 ...

  5. 解决Geoserver请求跨域的几种思路,第二种思路用过

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景描述 跨域问题是浏览器同源安全制引起的特别常见的问题.不同前端语 ...

  6. 关于set和map迭代器支持的运算

    问题: 曾经想遍历一个set遍历.当时是这样写的: set<int>::iterator b = a.begin()+1 后来发现程序报错.究其原因是,set迭代器不支持加减数操作. 查看 ...

  7. HTML XHTML HTNL5 简介

    XHTML 是HTML与XML(扩展标记语言)的结合物 包含了所有与XML语法结合的HTML 4.01元素 XHTML 指可扩展超文本标签语言(EXtensible HyperText Markup ...

  8. spring boot 配置双数据源mysql、sqlServer

    背景:原来一直都是使用mysql数据库,在application.properties 中配置数据库信息 spring.datasource.url=jdbc:mysql://xxxx/test sp ...

  9. 深入JVM对象引用

    在jdk 1.2以前,创建的对象只有处在可触及(reachaable)状态下,才能被程序所以使用,垃圾回收器一旦发现无用对象,便会对其进行回收.但是,在某些情况下,我们希望有些对象不需要立刻回收或者说 ...

  10. ashx和aspx的区别

    1. ashx是一般处理程序,一般返回的数据有两种,一种是html页面,一种是只返回一个字符串. 2. aspx是web窗体程序,每次新建都回自带一个界面和一个后台处理程序. 3. 根据以上两点,可以 ...