SpringJDBC无疑极大的方便了我们访问数据库,但是有一个小问题,每次查询操作返回的实体对象不一样,难道我们每次都要重新实现RowMapper吗?利用泛型,可以方便处理这样的操作。
开发环境:Windows10、eclipse、SpringJDBC4.3.7。文末含项目源码下载链接。
/*
* 文件名: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 implements RowMapper {
/**
* 添加字段注释.
*/
private Class> targetClazz;
/**
* 添加字段注释.
*/
private HashMap 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#建库字符编码为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;
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()方法,便于返回值查看。
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 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。
欢迎个人转载,但须在文章页面明显位置给出原文连接;
未经作者同意必须保留此段声明、不得随意修改原文、不得用于商业用途,否则保留追究法律责任的权利。
【 CSDN 】:csdn.zxiaofan.com
【GitHub】:github.zxiaofan.com
如有任何问题,欢迎留言。祝君好运!
Life is all about choices!
将来的你一定会感激现在拼命的自己!