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
- SpringJDBC之RowMapper通用类
- java网站建设6-封装Springjdbc的通用基类
- spring 中的 RowMapper 类
- SpringJDBC
- SpringJDBC
- SpringJDBC
- SpringJDBC
- springJDBC
- springjdbc
- springJDBC
- springmvc工具类封装RowMapper (未测试)
- Enterprise Library 5 数据访问之二、自定义RowMapper使用
- Spring JdbcTemplate实现通用的泛型dao四:通用自定义转换到JavaBean的RowMapper实现
- Spring JdbcTemplate实现通用的泛型dao四:通用自定义转换到JavaBean的RowMapper实现
- Spring 使用JdbcTemplate类实现批量查询(RowMapper)
- Spring-RowMapper
- Spring-RowMapper
- Spring-RowMapper
- closehandle()函数
- 把数组排成最小的数
- C++纯虚函数
- 2017华为软件精英挑战赛官方case最优解
- 二分法查找
- SpringJDBC之RowMapper通用类
- 设计模式(2)————简单工厂模式
- 仿qq气泡通知粘连效果
- Python pandas数据分析中常用方法
- 微信公众号
- CSS中强大的EM
- Codeforces Round #403 div2 (CodeForces
- HDU1285 确定比赛名次(拓扑排序+队列优化+链式前向星)
- 修改EditPlus的文本编码格式