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));
}


综上,轮子完毕。


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Spring Cloud JdbcTemplate是一个用于简化数据库访问的框架,可以方便地进行SQL操作。而分表查询是指将数据按照一定的规则拆分到多个表中,通过某种方式进行查询。在使用Spring Cloud JdbcTemplate进行分表查询时,可以按以下步骤进行操作: 1. 配置数据源:通过在Spring Boot配置文件中配置数据库连接信息,包括URL、用户名和密码等。可以使用JdbcTemplate的DataSource来获取数据库连接。 2. 创建数据库表:根据分表的规则,创建多个数据库表,并根据需要在表中添加索引等。 3. 定义数据访问对象(DAO):可以创建多个DAO来对应不同的分表,每个DAO中定义相应的查询方法。可以使用JdbcTemplate提供的方法来执行SQL语句,并将查询结果映射为Java对象。 4. 执行分表查询:根据业务需求,编写SQL查询语句,并使用JdbcTemplate提供的方法执行查询。在查询时,可以根据分表规则动态生成表名,并将查询结果返回。 5. 处理查询结果:根据需要对查询结果进行处理,可以对查询结果进行排序、分页等操作。 6. 销毁资源:在使用完JdbcTemplate后,需要销毁相关资源,包括关闭数据库连接等。 总结来说,通过Spring Cloud JdbcTemplate进行分表查询的过程是先配置数据源,然后创建数据库表和DAO,最后执行查询,并对查询结果进行处理。使用JdbcTemplate可以简化数据库访问的过程,提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值