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

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

1、自我实现RowMapper

[java] view plaincopy
  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. import java.lang.reflect.Field;
  11. import java.math.BigDecimal;
  12. import java.sql.ResultSet;
  13. import java.sql.ResultSetMetaData;
  14. import java.sql.SQLException;
  15. import java.sql.Timestamp;
  16. import java.util.Date;
  17. import java.util.HashMap;
  18. import org.springframework.jdbc.core.RowMapper;
  19. /**
  20. *
  21. * @author xiaofan
  22. */
  23. public class LocalRowMapper<T> implements RowMapper<T> {
  24. /**
  25. * 添加字段注释.
  26. */
  27. private Class<?> targetClazz;
  28. /**
  29. * 添加字段注释.
  30. */
  31. private HashMap<String, Field> fieldMap;
  32. /**
  33. * 构造函数.
  34. *
  35. * @param targetClazz
  36. *            .
  37. */
  38. public LocalRowMapper(Class<?> targetClazz) {
  39. this.targetClazz = targetClazz;
  40. fieldMap = new HashMap<>();
  41. Field[] fields = targetClazz.getDeclaredFields();
  42. for (Field field : fields) {
  43. // 同时存入大小写,如果表中列名区分大小写且有列ID和列iD,则会出现异常。
  44. // 阿里开发公约,建议表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字。
  45. fieldMap.put(field.getName(), field);
  46. // fieldMap.put(getFieldNameUpper(field.getName()), field);
  47. }
  48. }
  49. /**
  50. * {@inheritDoc}.
  51. */
  52. @Override
  53. public T mapRow(ResultSet rs, int arg1) throws SQLException {
  54. T obj = null;
  55. try {
  56. obj = (T) targetClazz.newInstance();
  57. final ResultSetMetaData metaData = rs.getMetaData();
  58. int columnLength = metaData.getColumnCount();
  59. String columnName = null;
  60. for (int i = 1; i <= columnLength; i++) {
  61. columnName = metaData.getColumnName(i);
  62. Class fieldClazz = fieldMap.get(columnName).getType();
  63. Field field = fieldMap.get(columnName);
  64. field.setAccessible(true);
  65. // fieldClazz == Character.class || fieldClazz == char.class
  66. if (fieldClazz == int.class || fieldClazz == Integer.class) { // int
  67. field.set(obj, rs.getInt(columnName));
  68. } else if (fieldClazz == boolean.class || fieldClazz == Boolean.class) { // boolean
  69. field.set(obj, rs.getBoolean(columnName));
  70. } else if (fieldClazz == String.class) { // string
  71. field.set(obj, rs.getString(columnName));
  72. } else if (fieldClazz == float.class) { // float
  73. field.set(obj, rs.getFloat(columnName));
  74. } else if (fieldClazz == double.class || fieldClazz == Double.class) { // double
  75. field.set(obj, rs.getDouble(columnName));
  76. } else if (fieldClazz == BigDecimal.class) { // bigdecimal
  77. field.set(obj, rs.getBigDecimal(columnName));
  78. } else if (fieldClazz == short.class || fieldClazz == Short.class) { // short
  79. field.set(obj, rs.getShort(columnName));
  80. } else if (fieldClazz == Date.class) { // date
  81. field.set(obj, rs.getDate(columnName));
  82. } else if (fieldClazz == Timestamp.class) { // timestamp
  83. field.set(obj, rs.getTimestamp(columnName));
  84. } else if (fieldClazz == Long.class || fieldClazz == long.class) { // long
  85. field.set(obj, rs.getLong(columnName));
  86. }
  87. field.setAccessible(false);
  88. }
  89. } catch (Exception e) {
  90. e.printStackTrace();
  91. }
  92. return obj;
  93. }
  94. /**
  95. * 方法首字母大写.
  96. *
  97. * @param fieldName
  98. *            字段名.
  99. * @return 字段名首字母大写.
  100. */
  101. private String getFieldNameUpper(String fieldName) {
  102. char[] cs = fieldName.toCharArray();
  103. cs[0] -= 32; // 方法首字母大写
  104. return String.valueOf(cs);
  105. }
  106. }

定义一个LocalRowMapper<T> 类,implements RowMapper<T>,在这里需要注意fieldMap缓存字段名,由于不同的人表字段命名规则不一样,有的习惯于首字母小写,有的习惯于首字母大写。这里以阿里巴巴开发公约为准(【强制】表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。)。如果你的表字段是大写开头,请注释掉fieldMap.put(field.getName(), field);同时放开fieldMap.put(getFieldNameUpper(field.getName()), field);这行的注释。

2、相关数据库表设计

[sql] view plaincopy
  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 plaincopy
  1. package com.zxiaofan.dubboProvidder.model;
  2. import java.util.Date;
  3. /**
  4. * 用户表.
  5. *
  6. * @author xiaofan
  7. */
  8. public class UserDo {
  9. private String tableName;
  10. private Integer id;
  11. private String userName;
  12. private Integer age;
  13. private Date addTime;
  14. private Date modifyTime;
  15. private int isDelete;
  16. // get/set方法略
  17. @Override
  18. public String toString() {
  19. return "UserDo [tableName=" + tableName + ", id=" + id + ", userName=" + userName + ", age=" + age + ", addTime=" + addTime + ", modifyTime=" + modifyTime + ", isDelete=" + isDelete + "]";
  20. }
  21. }

此处加入了数据库没有的字段tableName,方便数据库操作时传入表名,同时重写了toString()方法,便于返回值查看。

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

     app-context-dataSource.xml
[html] view plaincopy
  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. <!-- oracle.jdbc.driver.OracleDriver -->
  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 plaincopy
  1. package com.zxiaofan.dubboProvidder.business.impl;
  2. import java.util.List;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.jdbc.core.JdbcTemplate;
  5. import org.springframework.stereotype.Component;
  6. import com.zxiaofan.dubboProvidder.business.IUserBusiness;
  7. import com.zxiaofan.dubboProvidder.model.UserDo;
  8. import com.zxiaofan.dubboProvidder.rowMapper.LocalRowMapper;
  9. /**
  10. *
  11. * @author xiaofan
  12. */
  13. @Component
  14. public class UserBusinessImpl implements IUserBusiness {
  15. @Autowired
  16. private JdbcTemplate jdbcTemplate;
  17. /**
  18. * {@inheritDoc}.
  19. */
  20. @Override
  21. public int insert(UserDo userDo) {
  22. String sqlStr = "insert into " + userDo.getTableName() + " (userName,age,addTime,isDelete) values(?,?,?,?)";
  23. int result = jdbcTemplate.update(sqlStr, userDo.getUserName(), userDo.getAge(), userDo.getAddTime(), userDo.getIsDelete());
  24. return result;
  25. }
  26. /**
  27. * {@inheritDoc}.
  28. */
  29. @Override
  30. public UserDo selectByID(UserDo userDo) {
  31. String sqlStr = "select * from " + userDo.getTableName() + " where id=?";
  32. List<UserDo> dos = jdbcTemplate.query(sqlStr, new LocalRowMapper(UserDo.class), userDo.getId());
  33. if (null != dos && !dos.isEmpty()) {
  34. return dos.get(0);
  35. }
  36. return null;
  37. }
  38. /**
  39. * {@inheritDoc}.
  40. */
  41. @Override
  42. public int update(UserDo userDo) {
  43. String sqlStr = "update " + userDo.getTableName() + " set userName=? where id=?";
  44. int result = jdbcTemplate.update(sqlStr, userDo.getUserName(), userDo.getId());
  45. return result;
  46. }
  47. /**
  48. * {@inheritDoc}.
  49. */
  50. @Override
  51. public int delete(UserDo userDo) {
  52. String sqlStr = "delete from " + userDo.getTableName() + " where userName=?";
  53. int result = jdbcTemplate.update(sqlStr, userDo.getUserName());
  54. return result;
  55. }
  56. }

注意 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。

有任何问题,欢迎留言讨论。

[javascript] view plaincopy
  1. 欢迎个人转载,但须在文章页面明显位置给出原文连接;
  2. 未经作者同意必须保留此段声明、不得随意修改原文、不得用于商业用途,否则保留追究法律责任的权利。
  3. 【 CSDN 】:csdn.zxiaofan.com
  4. 【GitHub】:github.zxiaofan.com
  5. 如有任何问题,欢迎留言。祝君好运!
  6. Life is all about choices!
  7. 将来的你一定会感激现在拼命的自己!

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

SpringJDBC之RowMapper通用类相关推荐

  1. 一劳永逸,iOS 网页视图控制器通用类封装

    原文链接:http://www.jianshu.com/p/553424763585 随着 H5 的发展,在 iOS 开发中,网页视图的使用率逐渐提升,为了增加代码封装度.减轻开发负担,因此通常会对网 ...

  2. C#检测电脑的一些设置通用类(经典推荐)

    此类能检测出电脑的cpu序列号,获取网卡硬件地址,获取IP地址,获取硬盘ID,操作系统的登录用户名,PC类型,物理内存,就这些了,够用吧,谁在有能获取电脑别的信息的类,跟贴啊,欢迎大家分享,打造一个超 ...

  3. DataTable转ListModel通用类

    /// <summary> /// DataTable转List<Model>通用类[实体转换辅助类] /// </summary> public class Mo ...

  4. C#.NET操作数据库通用类(MS SQL Server篇)

    下面给出了一个C#操作MS SQL Server 数据库的通用类,通过该类可以对数据库进行任何操作,包括执行SQL语句.执行存储过程.以下是其详细实现过程,希望大家共同修改优化之.稍后将介绍如何使用它 ...

  5. C#.NET操作数据库通用类

    下面给出了一个C#操作MS SQL Server 数据库的通用类,通过该类可以对数据库进行任何操作,包括执行SQL语句.执行存储过程.以下是其详细实现过程,希望大家共同修改优化之.稍后将介绍如何使用它 ...

  6. 《WebForm开发系列高级篇》Item2导出EXCEL通用类(GridView,DataList,Repeater,DetailView)

    1.导出效果图: 2.C#导出EXCEL通用类源代码: using System; using System.Data; using System.Configuration; using Syste ...

  7. Memcached通用类(基于enyim.com Memcached Client)

    一.如果用官方提供的方法,在web.config里面配置好了各个参数和服务器IP.如下图: <?xml version="1.0"?> <configuratio ...

  8. C#:导入Excel通用类(CSV格式)

    一.引用插件LumenWorks.Framework.IO.dll(CsvReader) 插件下载地址:https://pan.baidu.com/s/1X9Sl4bWTNHJOJb_v-KUndA  ...

  9. 泛型类java_Java泛型 - 通用类( Generic Classes)

    Java泛型 - 通用类( Generic Classes) 泛型类声明看起来像非泛型类声明,除了类名后跟一个类型参数部分. 泛型类的类型参数部分可以有一个或多个用逗号分隔的类型参数. 这些类称为参数 ...

最新文章

  1. Open3D 三维点云读取可视化、下采样、去除离群点、地面提取
  2. Ruby用SciTE输出中文报错问题解决
  3. windows 驱动和应用层的三种通信方式 r3到r0 DeviceIoControl 4种ioctl请求
  4. 皮一皮:前女友竟然说这种话...
  5. 设计模式六:适配器模式
  6. 【牛客 - 157D】插排树(dfs,树形dp)
  7. pandas用众数填充缺失值_python数据分析包|Pandas-02之缺失值(NA)处理
  8. mysql 语句 not_mysql sql语句 is not 用法是
  9. 数据库优化的几种方法
  10. Code[VS]1997 守卫者的挑战
  11. Qt 窗口置顶 | 和取消置顶
  12. vos3000下载java_昆石VOS3000_2.1.4.0完整安装包及安装脚本
  13. java batik_使用BATIK解析SVG生成PNG图片
  14. Python+KinectV2——PyKinect
  15. flask 将route放置在多个文件中的方法(蓝本)
  16. java视频教程,Java面试资料
  17. MySQL查询,关于日期和时间戳,查询时间的记录
  18. matlab 动态识别,基于matlab脸部动态特征的人脸表情识别程序
  19. LaTex常用公式和字母
  20. ssm中报错: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type a

热门文章

  1. 基于javaweb框架的银行业务管理系统
  2. 高通平台5G注册问题分析
  3. Git学习(1)pro git阅读尚硅谷视频
  4. js插件+UploadFile类实现图片的批量上传
  5. 2022年系统架构师、案例分析、论文押题
  6. 神经网络机器翻译简单模型参考实现
  7. m6000查看端口状态_M6000日常查看维护命令
  8. Rem 字体设置学习
  9. vscode +git diff 快速定位修改差异
  10. vue-cli5脚手架搭建项目过程详解 -vue组件单元测试