SpringJDBC之RowMapper通用类

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

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

1、自我实现RowMapper

[java]  view plain  copy
  1. /* 
  2.  * 文件名:LocalRowMapper.java 
  3.  * 版权:Copyright 2007-2017 517na Tech. Co. Ltd. All Rights Reserved.  
  4.  * 描述: LocalRowMapper.java 
  5.  * 修改人:xiaofan 
  6.  * 修改时间:2017年3月19日 
  7.  * 修改内容:新增 
  8.  */  
  9. package com.zxiaofan.dubboProvidder.rowMapper;  
  10.   
  11. import java.lang.reflect.Field;  
  12. import java.math.BigDecimal;  
  13. import java.sql.ResultSet;  
  14. import java.sql.ResultSetMetaData;  
  15. import java.sql.SQLException;  
  16. import java.sql.Timestamp;  
  17. import java.util.Date;  
  18. import java.util.HashMap;  
  19.   
  20. import org.springframework.jdbc.core.RowMapper;  
  21.   
  22. /** 
  23.  *  
  24.  * @author xiaofan 
  25.  */  
  26. public class LocalRowMapper implements RowMapper {  
  27.   
  28.     /** 
  29.      * 添加字段注释. 
  30.      */  
  31.     private Class targetClazz;  
  32.   
  33.     /** 
  34.      * 添加字段注释. 
  35.      */  
  36.     private HashMap fieldMap;  
  37.   
  38.     /** 
  39.      * 构造函数. 
  40.      *  
  41.      * @param targetClazz 
  42.      *            . 
  43.      */  
  44.     public LocalRowMapper(Class targetClazz) {  
  45.         this.targetClazz = targetClazz;  
  46.         fieldMap = new HashMap<>();  
  47.         Field[] fields = targetClazz.getDeclaredFields();  
  48.         for (Field field : fields) {  
  49.             // 同时存入大小写,如果表中列名区分大小写且有列ID和列iD,则会出现异常。  
  50.             // 阿里开发公约,建议表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字。  
  51.             fieldMap.put(field.getName(), field);  
  52.             // fieldMap.put(getFieldNameUpper(field.getName()), field);  
  53.         }  
  54.     }  
  55.   
  56.     /** 
  57.      * {@inheritDoc}. 
  58.      */  
  59.     @Override  
  60.     public T mapRow(ResultSet rs, int arg1) throws SQLException {  
  61.         T obj = null;  
  62.   
  63.         try {  
  64.             obj = (T) targetClazz.newInstance();  
  65.   
  66.             final ResultSetMetaData metaData = rs.getMetaData();  
  67.             int columnLength = metaData.getColumnCount();  
  68.             String columnName = null;  
  69.   
  70.             for (int i = 1; i <= columnLength; i++) {  
  71.                 columnName = metaData.getColumnName(i);  
  72.                 Class fieldClazz = fieldMap.get(columnName).getType();  
  73.                 Field field = fieldMap.get(columnName);  
  74.                 field.setAccessible(true);  
  75.   
  76.                 // fieldClazz == Character.class || fieldClazz == char.class  
  77.                 if (fieldClazz == int.class || fieldClazz == Integer.class) { // int  
  78.                     field.set(obj, rs.getInt(columnName));  
  79.                 } else if (fieldClazz == boolean.class || fieldClazz == Boolean.class) { // boolean  
  80.                     field.set(obj, rs.getBoolean(columnName));  
  81.                 } else if (fieldClazz == String.class) { // string  
  82.                     field.set(obj, rs.getString(columnName));  
  83.                 } else if (fieldClazz == float.class) { // float  
  84.                     field.set(obj, rs.getFloat(columnName));  
  85.                 } else if (fieldClazz == double.class || fieldClazz == Double.class) { // double  
  86.                     field.set(obj, rs.getDouble(columnName));  
  87.                 } else if (fieldClazz == BigDecimal.class) { // bigdecimal  
  88.                     field.set(obj, rs.getBigDecimal(columnName));  
  89.                 } else if (fieldClazz == short.class || fieldClazz == Short.class) { // short  
  90.                     field.set(obj, rs.getShort(columnName));  
  91.                 } else if (fieldClazz == Date.class) { // date  
  92.                     field.set(obj, rs.getDate(columnName));  
  93.                 } else if (fieldClazz == Timestamp.class) { // timestamp  
  94.                     field.set(obj, rs.getTimestamp(columnName));  
  95.                 } else if (fieldClazz == Long.class || fieldClazz == long.class) { // long  
  96.                     field.set(obj, rs.getLong(columnName));  
  97.                 }  
  98.   
  99.                 field.setAccessible(false);  
  100.             }  
  101.         } catch (Exception e) {  
  102.             e.printStackTrace();  
  103.         }  
  104.   
  105.         return obj;  
  106.     }  
  107.   
  108.     /** 
  109.      * 方法首字母大写. 
  110.      *  
  111.      * @param fieldName 
  112.      *            字段名. 
  113.      * @return 字段名首字母大写. 
  114.      */  
  115.     private String getFieldNameUpper(String fieldName) {  
  116.         char[] cs = fieldName.toCharArray();  
  117.         cs[0] -= 32// 方法首字母大写  
  118.         return String.valueOf(cs);  
  119.     }  
  120. }  
        定义一个 LocalRowMapper 类,implements  RowMapper,在这里需要注意fieldMap缓存字段名,由于不同的人表字段命名规则不一样,有的习惯于首字母小写,有的习惯于首字母大写。这里以阿里巴巴开发公约为准( 【强制】表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。)。如果你的表字段是大写开头,请注释掉fieldMap.put(field.getName(), field);同时放开fieldMap.put(getFieldNameUpper(field.getName()), field);这行的注释。

2、相关数据库表设计

[sql]  view plain  copy
  1. #建库字符编码为utf8的库studydb  
  2. CREATE DATABASE IF NOT EXISTS StudyDB DEFAULT CHARACTER SET utf8;  
  3. #建表user  
  4. CREATE TABLE  
  5. IF NOT EXISTS USER (  
  6.     id INT (10) NOT NULL auto_increment,  
  7.     userName VARCHAR (20) NOT NULL,  
  8.     age INT (4),  
  9.     addTime DATETIME,  
  10.     modifyTime TIMESTAMP,  
  11.     isDelete INT(4),  
  12.     PRIMARY KEY (id)  
  13. ) ENGINE = INNODB DEFAULT CHARSET = utf8;  

3、定义model

[java]  view plain  copy
  1. package com.zxiaofan.dubboProvidder.model;  
  2.   
  3. import java.util.Date;  
  4.   
  5. /** 
  6.  * 用户表. 
  7.  *  
  8.  * @author xiaofan 
  9.  */  
  10. public class UserDo {  
  11.     private String tableName;  
  12.   
  13.     private Integer id;  
  14.   
  15.     private String userName;  
  16.   
  17.     private Integer age;  
  18.   
  19.     private Date addTime;  
  20.   
  21.     private Date modifyTime;  
  22.   
  23.     private int isDelete;  
  24.   
  25.     // get/set方法略  
  26.     @Override  
  27.     public String toString() {  
  28.         return "UserDo [tableName=" + tableName + ", id=" + id + ", userName=" + userName + ", age=" + age + ", addTime=" + addTime + ", modifyTime=" + modifyTime + ", isDelete=" + isDelete + "]";  
  29.     }  
  30.   
  31. }  
        此处加入了数据库没有的字段tableName,方便数据库操作时传入表名,同时重写了toString()方法,便于返回值查看。

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

     app-context-dataSource.xml
[html]  view plain  copy
  1. xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  5.     http://www.springframework.org/schema/beans/spring-beans-4.3.xsd    
  6.     http://code.alibabatech.com/schema/dubbo    
  7.     http://code.alibabatech.com/schema/dubbo/dubbo.xsd">  
  8.       
  9.     <bean id="dataSource"  
  10.         class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  11.         <property name="driverClassName" value="${jdbc.driver}">  
  12.         property>  
  13.         <property name="url" value="${jdbc.url}">  
  14.         property>  
  15.         <property name="username" value="${jdbc.username}">property>  
  16.         <property name="password" value="${jdbc.password}">property>  
  17.     bean>  
  18.     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"  
  19.         abstract="false" lazy-init="false" autowire="default">  
  20.         <property name="dataSource">  
  21.             <ref bean="dataSource" />  
  22.         property>  
  23.     bean>  
  24. beans>  

4、具体使用

[java]  view plain  copy
  1. package com.zxiaofan.dubboProvidder.business.impl;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.jdbc.core.JdbcTemplate;  
  7. import org.springframework.stereotype.Component;  
  8.   
  9. import com.zxiaofan.dubboProvidder.business.IUserBusiness;  
  10. import com.zxiaofan.dubboProvidder.model.UserDo;  
  11. import com.zxiaofan.dubboProvidder.rowMapper.LocalRowMapper;  
  12.   
  13. /** 
  14.  *  
  15.  * @author xiaofan 
  16.  */  
  17. @Component  
  18. public class UserBusinessImpl implements IUserBusiness {  
  19.     @Autowired  
  20.     private JdbcTemplate jdbcTemplate;  
  21.   
  22.     /** 
  23.      * {@inheritDoc}. 
  24.      */  
  25.     @Override  
  26.     public int insert(UserDo userDo) {  
  27.         String sqlStr = "insert into " + userDo.getTableName() + " (userName,age,addTime,isDelete) values(?,?,?,?)";  
  28.         int result = jdbcTemplate.update(sqlStr, userDo.getUserName(), userDo.getAge(), userDo.getAddTime(), userDo.getIsDelete());  
  29.         return result;  
  30.     }  
  31.   
  32.     /** 
  33.      * {@inheritDoc}. 
  34.      */  
  35.     @Override  
  36.     public UserDo selectByID(UserDo userDo) {  
  37.         String sqlStr = "select * from " + userDo.getTableName() + " where id=?";  
  38.         List dos = jdbcTemplate.query(sqlStr, new LocalRowMapper(UserDo.class), userDo.getId());  
  39.         if (null != dos && !dos.isEmpty()) {  
  40.             return dos.get(0);  
  41.         }  
  42.         return null;  
  43.     }  
  44.   
  45.     /** 
  46.      * {@inheritDoc}. 
  47.      */  
  48.     @Override  
  49.     public int update(UserDo userDo) {  
  50.         String sqlStr = "update " + userDo.getTableName() + " set userName=? where id=?";  
  51.         int result = jdbcTemplate.update(sqlStr, userDo.getUserName(), userDo.getId());  
  52.         return result;  
  53.     }  
  54.   
  55.     /** 
  56.      * {@inheritDoc}. 
  57.      */  
  58.     @Override  
  59.     public int delete(UserDo userDo) {  
  60.         String sqlStr = "delete from " + userDo.getTableName() + " where userName=?";  
  61.         int result = jdbcTemplate.update(sqlStr, userDo.getUserName());  
  62.         return result;  
  63.     }  
  64.   
  65. }  
        注意 UserDo  selectByID(UserDo userDo) 方法,jdbcTemplate. query(sqlStr,  new LocalRowMapper(UserDo.class), userDo.getId());入参为sql、重写的 LocalRowMapper、实际参数id,这里我们传入了返回实体对象UserDo的的类类型UserDo.class。待数据返回后将自动映射成我们的model。
        查看单元测试情况,这里只展示根据KeyID查询的,其他请自行执行测试类。
SpringJDBC之RowMapper通用类_第1张图片
        下图是测试暴露的HTTP服务,详见另一篇博文《 dubbo使用教程,可直接应用于企业开发》
SpringJDBC之RowMapper通用类_第2张图片


         源码地址:https://github.com/zxiaofan/OpenSource_Study/tree/master/dubbo/DubboProvider,以上代码来源于个人学习项目dubbo,项目OpenSource_Study下包含了本人各类开源软件、框架学习的相关demo,包含Apache、Thrift、Guava、quartz等项目,持续学习ing。
        有任何问题,欢迎留言讨论。
[javascript]  view plain  copy
  1. 欢迎个人转载,但须在文章页面明显位置给出原文连接;  
  2. 未经作者同意必须保留此段声明、不得随意修改原文、不得用于商业用途,否则保留追究法律责任的权利。  
  3.   
  4. 【 CSDN 】:csdn.zxiaofan.com  
  5. 【GitHub】:github.zxiaofan.com  
  6.   
  7. 如有任何问题,欢迎留言。祝君好运!  
  8. Life is all about choices!   
  9. 将来的你一定会感激现在拼命的自己!  

你可能感兴趣的:(编程,后端)