SpringJDBC之RowMapper通用类

版权声明:【分享也是一种提高】个人转载请在正文开头明显位置注明出处,未经作者同意禁止企业/组织转载,禁止私自更改原文,禁止用于商业目的。 https://blog.csdn.net/u010887744/article/details/64216979

        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的库studydb
CREATE DATABASE IF NOT EXISTS StudyDB DEFAULT CHARACTER SET utf8;
#建表user
CREATE TABLE
IF 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
 */
@Component
public 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。
        有任何问题,欢迎留言讨论。
欢迎个人转载,但须在文章页面明显位置给出原文连接;
未经作者同意必须保留此段声明、不得随意修改原文、不得用于商业用途,否则保留追究法律责任的权利。

【 CSDN 】:csdn.zxiaofan.com
【GitHub】:github.zxiaofan.com

如有任何问题,欢迎留言。祝君好运!
Life is all about choices! 
将来的你一定会感激现在拼命的自己!

没有更多推荐了,返回首页