SpringJDBC之RowMapper通用类

来源:互联网 发布:中信证券待遇 知乎 编辑:程序博客网 时间:2024/06/05 07:58

        SpringJDBC无疑极大的方便了我们访问数据库,但是有一个小问题,每次查询操作返回的实体对象不一样,难道我们每次都要重新实现RowMapper吗?利用泛型,可以方便处理这样的操作。

        开发环境:Windows10、eclipse、SpringJDBC4.3.7。文末含项目源码下载链接

1、自我实现RowMapper

/* * 文件名:LocalRowMapper.java * 版权:Copyright 2007-2017 517na Tech. Co. Ltd. All Rights Reserved.  * 描述: LocalRowMapper.java * 修改人:xiaofan * 修改时间:2017年3月19日 * 修改内容:新增 */package com.zxiaofan.dubboProvidder.rowMapper;import java.lang.reflect.Field;import java.math.BigDecimal;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;import java.sql.Timestamp;import java.util.Date;import java.util.HashMap;import org.springframework.jdbc.core.RowMapper;/** *  * @author xiaofan */public class LocalRowMapper<T> implements RowMapper<T> {    /**     * 添加字段注释.     */    private Class<?> targetClazz;    /**     * 添加字段注释.     */    private HashMap<String, Field> fieldMap;    /**     * 构造函数.     *      * @param targetClazz     *            .     */    public LocalRowMapper(Class<?> targetClazz) {        this.targetClazz = targetClazz;        fieldMap = new HashMap<>();        Field[] fields = targetClazz.getDeclaredFields();        for (Field field : fields) {            // 同时存入大小写,如果表中列名区分大小写且有列ID和列iD,则会出现异常。            // 阿里开发公约,建议表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字。            fieldMap.put(field.getName(), field);            // fieldMap.put(getFieldNameUpper(field.getName()), field);        }    }    /**     * {@inheritDoc}.     */    @Override    public T mapRow(ResultSet rs, int arg1) throws SQLException {        T obj = null;        try {            obj = (T) targetClazz.newInstance();            final ResultSetMetaData metaData = rs.getMetaData();            int columnLength = metaData.getColumnCount();            String columnName = null;            for (int i = 1; i <= columnLength; i++) {                columnName = metaData.getColumnName(i);                Class fieldClazz = fieldMap.get(columnName).getType();                Field field = fieldMap.get(columnName);                field.setAccessible(true);                // fieldClazz == Character.class || fieldClazz == char.class                if (fieldClazz == int.class || fieldClazz == Integer.class) { // int                    field.set(obj, rs.getInt(columnName));                } else if (fieldClazz == boolean.class || fieldClazz == Boolean.class) { // boolean                    field.set(obj, rs.getBoolean(columnName));                } else if (fieldClazz == String.class) { // string                    field.set(obj, rs.getString(columnName));                } else if (fieldClazz == float.class) { // float                    field.set(obj, rs.getFloat(columnName));                } else if (fieldClazz == double.class || fieldClazz == Double.class) { // double                    field.set(obj, rs.getDouble(columnName));                } else if (fieldClazz == BigDecimal.class) { // bigdecimal                    field.set(obj, rs.getBigDecimal(columnName));                } else if (fieldClazz == short.class || fieldClazz == Short.class) { // short                    field.set(obj, rs.getShort(columnName));                } else if (fieldClazz == Date.class) { // date                    field.set(obj, rs.getDate(columnName));                } else if (fieldClazz == Timestamp.class) { // timestamp                    field.set(obj, rs.getTimestamp(columnName));                } else if (fieldClazz == Long.class || fieldClazz == long.class) { // long                    field.set(obj, rs.getLong(columnName));                }                field.setAccessible(false);            }        } catch (Exception e) {            e.printStackTrace();        }        return obj;    }    /**     * 方法首字母大写.     *      * @param fieldName     *            字段名.     * @return 字段名首字母大写.     */    private String getFieldNameUpper(String fieldName) {        char[] cs = fieldName.toCharArray();        cs[0] -= 32; // 方法首字母大写        return String.valueOf(cs);    }}
        定义一个LocalRowMapper<T> 类,implements RowMapper<T>,在这里需要注意fieldMap缓存字段名,由于不同的人表字段命名规则不一样,有的习惯于首字母小写,有的习惯于首字母大写。这里以阿里巴巴开发公约为准(【强制】表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。)。如果你的表字段是大写开头,请注释掉fieldMap.put(field.getName(), field);同时放开fieldMap.put(getFieldNameUpper(field.getName()), field);这行的注释。

2、相关数据库表设计

#建库字符编码为utf8的库studydbCREATE DATABASE IF NOT EXISTS StudyDB DEFAULT CHARACTER SET utf8;#建表userCREATE TABLEIF NOT EXISTS USER (id INT (10) NOT NULL auto_increment,userName VARCHAR (20) NOT NULL,age INT (4),addTime DATETIME,modifyTime TIMESTAMP,isDelete INT(4),PRIMARY KEY (id)) ENGINE = INNODB DEFAULT CHARSET = utf8;

3、定义model

package com.zxiaofan.dubboProvidder.model;import java.util.Date;/** * 用户表. *  * @author xiaofan */public class UserDo {    private String tableName;    private Integer id;    private String userName;    private Integer age;    private Date addTime;    private Date modifyTime;    private int isDelete;    // get/set方法略    @Override    public String toString() {        return "UserDo [tableName=" + tableName + ", id=" + id + ", userName=" + userName + ", age=" + age + ", addTime=" + addTime + ", modifyTime=" + modifyTime + ", isDelete=" + isDelete + "]";    }}
        此处加入了数据库没有的字段tableName,方便数据库操作时传入表名,同时重写了toString()方法,便于返回值查看。

3、数据库相关配置及注入jdbcTemplate

     app-context-dataSource.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd      http://code.alibabatech.com/schema/dubbo      http://code.alibabatech.com/schema/dubbo/dubbo.xsd"><!-- oracle.jdbc.driver.OracleDriver --><bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="${jdbc.driver}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"abstract="false" lazy-init="false" autowire="default"><property name="dataSource"><ref bean="dataSource" /></property></bean></beans>

4、具体使用

package com.zxiaofan.dubboProvidder.business.impl;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Component;import com.zxiaofan.dubboProvidder.business.IUserBusiness;import com.zxiaofan.dubboProvidder.model.UserDo;import com.zxiaofan.dubboProvidder.rowMapper.LocalRowMapper;/** *  * @author xiaofan */@Componentpublic class UserBusinessImpl implements IUserBusiness {    @Autowired    private JdbcTemplate jdbcTemplate;    /**     * {@inheritDoc}.     */    @Override    public int insert(UserDo userDo) {        String sqlStr = "insert into " + userDo.getTableName() + " (userName,age,addTime,isDelete) values(?,?,?,?)";        int result = jdbcTemplate.update(sqlStr, userDo.getUserName(), userDo.getAge(), userDo.getAddTime(), userDo.getIsDelete());        return result;    }    /**     * {@inheritDoc}.     */    @Override    public UserDo selectByID(UserDo userDo) {        String sqlStr = "select * from " + userDo.getTableName() + " where id=?";        List<UserDo> dos = jdbcTemplate.query(sqlStr, new LocalRowMapper(UserDo.class), userDo.getId());        if (null != dos && !dos.isEmpty()) {            return dos.get(0);        }        return null;    }    /**     * {@inheritDoc}.     */    @Override    public int update(UserDo userDo) {        String sqlStr = "update " + userDo.getTableName() + " set userName=? where id=?";        int result = jdbcTemplate.update(sqlStr, userDo.getUserName(), userDo.getId());        return result;    }    /**     * {@inheritDoc}.     */    @Override    public int delete(UserDo userDo) {        String sqlStr = "delete from " + userDo.getTableName() + " where userName=?";        int result = jdbcTemplate.update(sqlStr, userDo.getUserName());        return result;    }}
        注意 UserDo selectByID(UserDo userDo) 方法,jdbcTemplate.query(sqlStr,new LocalRowMapper(UserDo.class), userDo.getId());入参为sql、重写的LocalRowMapper、实际参数id,这里我们传入了返回实体对象UserDo的的类类型UserDo.class。待数据返回后将自动映射成我们的model。
        查看单元测试情况,这里只展示根据KeyID查询的,其他请自行执行测试类。

        下图是测试暴露的HTTP服务,详见另一篇博文《dubbo使用教程,可直接应用于企业开发》



        源码地址:https://github.com/zxiaofan/OpenSource_Study/tree/master/dubbo/DubboProvider,以上代码来源于个人学习项目dubbo,项目OpenSource_Study下包含了本人各类开源软件、框架学习的相关demo,包含Apache、Thrift、Guava、quartz等项目,持续学习ing。
        有任何问题,欢迎留言讨论。

1 0
原创粉丝点击