您的位置:首页 > 编程语言 > Java开发

JDBC的一些通用封装+动态代理做缓存存取(自动解析返回的数据装载成实体类)

2018-01-15 14:48 465 查看
最近一个项目要用微服务改造,但是已有SQL很复杂感觉不适合用JPA,于是自己封装了下JDBC,以下代码也算是做下笔记吧。

PS:由于没有分页查询的需求所以没做分页功能。

public interface BaseDao {

public <T> List<T> find(String sql,Class<T> clazz, Object... params);

/**
* @Title: find
* @Description: TODO(查询,参数是数组)
* @param @param sql
* @param @param clazz
* @param @param params
* @param @return
* @return T 返回类型
* @date 2017年12月5日
*/
public <T> List<T> find(String sql,Class<T> clazz, List<?> params);

/**
* @Title: getProxy
* @Description: TODO(获得BaseDao的代理对象)
* @param @param clazz 查询返回结果对象的类型
* @param @return
* @return BaseDao 返回代理对象BaseDao
* @date 2017年12月1日
*/
public <T> BaseDao getProxy(Class<T> clazz);

public boolean insert(String sql, Object... params);

public boolean insert(String sql, List<?> params);

public boolean update(String sql,Object... params);

public <T> T find(String sql,Class<T> clazz, Object params);

}basedao 实现类:
@Component
public class BaseDaoImpl implements BaseDao{
@Autowired
private Dialect dialect;
@Autowired
private DataSource ds;
@Autowired
ICtgCacheManager cache;

public boolean insert(String sql, Object... params){
return excuteUpdate(sql,params)>0?true:false;
}

public boolean insert(String sql, List<?> params){
return excuteUpdate(sql,params)>0?true:false;
}

public boolean update(String sql,Object... params){
return excuteUpdate(sql,params)>0?true:false;
}

public <T> T find(String sql,Class<T> clazz, Object params){
List<T> list = excuteQuery(sql,clazz,params);
if(list!=null&&list.size()>0){
return list.get(0);
}
return null;
}

public <T> List<T> find(String sql,Class<T> clazz, Object... params) {
return excuteQuery(sql,clazz,params);
}

public <T> List<T> find(String sql,Class<T> clazz,List<?> params) {
return excuteQuery(sql,clazz,params);
}

private <T> int excuteUpdate(String sql,Object... params){
Connection conn = null;
try {
conn = ds.getConnection();
PaasLogger.info("Excute Sql:{}", sql);
PreparedStatement pst = conn.prepareStatement(sql);
prepareValue(pst, params);
return pst.executeUpdate();
} catch (SQLException e) {
PaasLogger.error("操作数据库出错!{}", e.getMessage());
e.printStackTrace();
return -1;
}finally {
closeConnection(conn);
}
}

private <T> int excuteUpdate(String sql,List<?> params){
Connection conn = null;
try {
conn = ds.getConnection();
PaasLogger.info("Excute Sql:{}", sql);
PreparedStatement pst = conn.prepareStatement(sql);
prepareValue(pst, params);
return pst.executeUpdate();
} catch (SQLException e) {
PaasLogger.error("操作数据库出错!{}", e.getMessage());
e.printStackTrace();
return -1;
}finally {
closeConnection(conn);
}
}

private <T> List<T> excuteQuery(String sql,Class<T> clazz, Object... params){
Connection conn = null;
try {
conn = ds.getConnection();
PaasLogger.info("Excute Sql:{}", sql);
PreparedStatement pst = conn.prepareStatement(sql);
prepareValue(pst, params);
ResultSet rs = pst.executeQuery();
return mapRersultSetToObject(rs,clazz);
} catch (SQLException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
PaasLogger.error("查询数据库出错!{}", e.getMessage());
e.printStackTrace();
return null;
}finally {
closeConnection(conn);
}
}

private <T> List<T> excuteQuery(String sql,Class<T> clazz, List<?> params){
Connection conn = null;
try {
conn = ds.getConnection();
PaasLogger.info("Excute Sql:{}", sql);
PreparedStatement pst = conn.prepareStatement(sql);
prepareValue(pst, params);
ResultSet rs = pst.executeQuery();
return mapRersultSetToObject(rs,clazz);
} catch (SQLException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
PaasLogger.error("查询数据库出错!{}", e.getMessage());
e.printStackTrace();
return null;
}finally {
closeConnection(conn);
}
}

private void closeConnection(Connection conn){
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}

private void prepareValue(PreparedStatement pst,List<?> params) throws SQLException {
int index = 1;
for (Object param : params) {
if(param!=null&&!param.equals("")){
dialect.setValue(pst, param, index);
index++;
}
}
}

private void prepareValue(PreparedStatement pst, Object... params) throws SQLException {
int index = 1;
for (Object param : params) {
if(param!=null&&!param.equals("")){
dialect.setValue(pst, param, index);
index++;
}
}
}

public <T> List<T> mapRersultSetToObject(ResultSet rs, Class<T> outputClass) throws SQLException, InstantiationException, IllegalAccessException, InvocationTargetException {
List<T> outputList = null;
// make sure resultset is not null
if (rs != null) {
// get the resultset metadata
ResultSetMetaData rsmd = rs.getMetaData();
// get all the attributes of outputClass
Field[] fields = outputClass.getDeclaredFields();
while (rs.next()) {
T bean = (T) outputClass.newInstance();
for (int _iterator = 0; _iterator < rsmd.getColumnCount(); _iterator++) {
//优先获取别名
String columnName = rsmd.getColumnLabel(_iterator + 1);
if(columnName==null||columnName.trim().equals("")){
columnName = rsmd.getColumnName(_iterator + 1);
}
// reading the value of the SQL column
Object columnValue = rs.getObject(_iterator + 1);
for (Field field : fields) {
if(!field.getName().equalsIgnoreCase(columnName))
columnName = camelName(columnName);
if (field.getName().equalsIgnoreCase(columnName) && columnValue != null) {
BeanUtils.setProperty(bean, field.getName(), columnValue);
break;
}
}
}
if (outputList == null) {
outputList = new ArrayList<T>();
}
outputList.add(bean);
}
} else {
return null;
}
return outputList;
}

private String camelName(String name) {
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty()) {
// 没必要转换
return "";
} else if (!name.contains("_")) {
// 不含下划线,仅将首字母小写
return name.substring(0, 1).toLowerCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String camels[] = name.split("_");
for (String camel : camels) {
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty()) {
continue;
}

// 处理真正的驼峰片段
if (result.length() == 0) {

// 第一个驼峰片段,全部字母都小写
result.append(camel.toLowerCase());

} else {
// 其他的驼峰片段,首字母大写
result.append(camel.substring(0, 1).toUpperCase());

result.append(camel.substring(1).toLowerCase());
}
}
return result.toString();

}

public <T> BaseDao getProxy(Class<T> clazz) {
InvocationHandler invocationHandler = new MyInvocationHandler(this,cache,clazz);
return (BaseDao)Proxy.newProxyInstance(this.getClass().getClassLoader(),
this.getClass().getInterfaces(), invocationHandler);
}

上面的dataSource是spring注入的,JDBC连接框架是已经配置好了的。
public class BaseService {

@Autowired
private BaseDao baseDao;

@InitBinder
protected void initBinder(WebDataBinder binder) {
//解除spring mvc list参数限制长度问题
//binder.setAutoGrowCollectionLimit(1024);
binder.registerCustomEditor(Date.class,
new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}

public <T> List<T> findList(String sql, Class<T> clazz, Object... params) {
return baseDao.getProxy(clazz).find(sql, clazz, params);
}

public <T> List<T> findList(String sql, Class<T> clazz,List<?> params) {
return baseDao.getProxy(clazz).find(sql, clazz, params);
}

public <T> T find(String sql, Class<T> clazz, Object params) {
return baseDao.getProxy(clazz).find(sql, clazz, params);
}

public boolean insert(String sql){
return baseDao.insert(sql);
}

public boolean insert(String sql,Object...params){
return baseDao.insert(sql,params);
}

public boolean insert(String sql,List<?> params){
return baseDao.insert(sql,params);
}

public boolean update(String sql,Object... params){
return baseDao.update(sql, params);
}以上查询方法都是先拿代理对象再调用JDBC方法,为的是走缓存,而增删是直接调用。
下面两个类是BaseDao需要用到的实体类

public class ColumnInfo {
private String name;

private int idx;

private int type;

public ColumnInfo(String name, int idx, int type) {
super();
this.name = name;
this.idx = idx;
this.type = type;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getIdx() {
return idx;
}

public void setIdx(int idx) {
this.idx = idx;
}

public int getType() {
return type;
}

public void setType(int type) {
this.type = type;
}
@Component
public class Dialect {

@SuppressWarnings("unchecked")
public void fillStatement(PreparedStatement pst, Object... paras) throws SQLException {
if (paras.length > 0) {
Object value = paras[0];
if (value instanceof Collection) {
fillStatementArray(pst, ((Collection<Object>) value).toArray());
} else {
fillStatementArray(pst, paras);
}
}
}

private void fillStatementArray(PreparedStatement pst, Object[] paras) throws SQLException {
for (int i = 0, length = paras.length; i < length;) {
Object value = paras[i++];
setValue(pst, value, i);
}
}

//	private void fillStatementList(PreparedStatement pst, List<Object> paras) throws SQLException {
//		for (int i = 0, size = paras.size(); i < size;) {
//			Object value = paras.get(i++);
//			setValue(pst, value, i);
//		}
//	}

public void setValue(PreparedStatement stmt, Object value, int index) throws SQLException {
if (value == null) {
stmt.setObject(index, null);
} else if (String.class.equals(value.getClass())) {
stmt.setString(index, (String) value);
} else if (Integer.class.equals(value.getClass())) {
stmt.setInt(index, (Integer) value);
} else if (Long.class.equals(value.getClass())) {
stmt.setLong(index, (Long) value);
} else if (Double.class.equals(value.getClass())) {
stmt.setDouble(index, (Double) value);
} else if (Float.class.equals(value.getClass())) {
stmt.setFloat(index, (Float) value);
} else if (value instanceof Calendar) {
long inMillis = ((Calendar) value).getTimeInMillis();
stmt.setTimestamp(index, new Timestamp(inMillis));
} else if (value instanceof Date) {
long time = ((Date) value).getTime();
stmt.setTimestamp(index, new Timestamp(time));
} else if (value instanceof java.util.Date) {
long time = ((java.util.Date) value).getTime();
stmt.setTimestamp(index, new Timestamp(time));
} else if (Boolean.class.equals(value.getClass())) {
stmt.setBoolean(index, (Boolean) value);
} else if (Byte.class.equals(value.getClass())) {
stmt.setByte(index, (Byte) value);
} else if (Short.class.equals(value.getClass())) {
stmt.setShort(index, (Short) value);
} else if (Character.class.equals(value.getClass())) {
stmt.setString(index, value.toString());
} else if (BigDecimal.class.equals(value.getClass())) {
stmt.setBigDecimal(index, (BigDecimal) value);
} else {
stmt.setObject(index, value);
}
}

public String buildCountSql(String sql) {
sql = sql.replaceAll("(\\s)+", " ").toLowerCase();
sql = replaceFormatSqlOrderBy(sql);
if (sql.indexOf("distinct") > -1) {
return new StringBuilder(sql.length() + 24).append("select count(*) cnt from ( ").append(sql).append(" ) temp_ ").toString();
} else {
int index = sql.lastIndexOf("from");
if (index != -1) {
String subSql = sql.substring(index);
return new StringBuilder(subSql.length() + 24).append("select count(*) cnt ").append(subSql).toString();
}
}
return sql;
}

public Object convertValue(ColumnInfo info, ResultSet rs, Type javaType) throws SQLException, IOException {
Object value = null;
int type = info.getType();
int idx = info.getIdx();
switch (type) {
case Types.CHAR:
String str = rs.getString(idx);
value = StringUtil.empty(str) ? str : ConverterUtil.string2Other(str, javaType);
break;
case Types.VARCHAR:
str = rs.getString(idx);
value = StringUtil.empty(str) ? str : ConverterUtil.string2Other(str, javaType);
break;
case Types.LONGVARCHAR:
str = rs.getString(idx);
value = StringUtil.empty(str) ? str : ConverterUtil.string2Other(str, javaType);
break;
case Types.NUMERIC:
BigDecimal bd = rs.getBigDecimal(idx);
if (bd != null) {
value = ConverterUtil.bigDecimal2Other(bd, javaType);
}
break;
case Types.DECIMAL:
bd = rs.getBigDecimal(idx);
if (bd != null) {
value = ConverterUtil.bigDecimal2Other(bd, javaType);
}
break;
case Types.BIT:
if (Boolean.class == javaType || boolean.class == javaType) {
value = rs.getBoolean(idx);
break;
}
str = rs.getString(idx);
value = StringUtil.empty(str) ? str : ConverterUtil.string2Other(str, javaType);
break;
case Types.TINYINT:
value = rs.getByte(idx);
break;
case Types.SMALLINT:
Short s = rs.getShort(idx);
if (s != null) {
value = ConverterUtil.bigDecimal2Other(new BigDecimal(s), javaType);
}
break;
case Types.INTEGER:
Integer i = rs.getInt(idx);
if (i != null) {
value = ConverterUtil.bigDecimal2Other(new BigDecimal(i), javaType);
}
break;
case Types.BIGINT:
Long l = rs.getLong(idx);
if (l != null) {
value = ConverterUtil.bigDecimal2Other(new BigDecimal(l), javaType);
}
break;
case Types.REAL:
value = rs.getFloat(idx);
break;
case Types.FLOAT:
Double d = rs.getDouble(idx);
if (d != null) {
value = ConverterUtil.double2Other(d, javaType);
}
break;
case Types.DOUBLE:
d = rs.getDouble(idx);
if (d != null) {
value = ConverterUtil.double2Other(d, javaType);
}
break;
case Types.BINARY:
byte[] bytes = rs.getBytes(idx);
if (bytes != null) {
value = ConverterUtil.bytes2Other(bytes, javaType);
}
break;
case Types.VARBINARY:
bytes = rs.getBytes(idx);
value = ConverterUtil.bytes2Other(bytes, javaType);
break;
case Types.LONGVARBINARY:
bytes = rs.getBytes(idx);
if (bytes != null) {
value = ConverterUtil.bytes2Other(bytes, javaType);
}
break;
case Types.DATE:
Date date = rs.getDate(idx);
if (date != null) {
value = ConverterUtil.date2Other(date, javaType);
}
break;
case Types.TIME:
Time time = rs.getTime(idx);
if (time != null) {
value = ConverterUtil.time2Other(time, javaType);
}
break;
case Types.TIMESTAMP:
Timestamp timestamp = rs.getTimestamp(idx);
if (timestamp != null) {
value = ConverterUtil.timestamp2Other(timestamp, javaType);
}
break;
case Types.BLOB:
Blob blob = rs.getBlob(idx);
if (blob != null) {
bytes = ConverterUtil.handleBlob(blob);
value = ConverterUtil.bytes2Other(bytes, javaType);
}
break;
case Types.CLOB:
Clob clob = rs.getClob(idx);
if (clob != null) {
value = ConverterUtil.handleClob(clob);
}
break;
case Types.NCLOB:
clob = rs.getClob(idx);
if (clob != null) {
value = ConverterUtil.handleClob(clob);
}
break;
case Types.ARRAY:
value = rs.getArray(idx);
break;
case Types.REF:
value = rs.getRef(idx);
break;
default:
break;
}
return value;
}

//	@SuppressWarnings("unchecked")
//	public List<Object> fillPageStatement(PreparedStatement pst, PageSql pageSql, Object... paras) throws SQLException {
//		List<Object> obj = null;
//		if (paras != null && paras.length > 0) {
//			Object value = paras[0];
//			if (value instanceof Collection) {
//				obj = (List<Object>) value;
//			} else {
//				obj = new ArrayList<Object>();
//				for (Object object : paras) {
//					obj.add(object);
//				}
//			}
//			obj.add(pageSql.getStart());
//			obj.add(pageSql.getEnd());
//			fillStatementList(pst, obj);
//		} else {
//			obj = fillStatement(pst, pageSql.getStart(), pageSql.getEnd());
//		}
//		return obj;
//	}
//
//	public Object getData(ResultSet rs, int[] types, int i) throws SQLException, IOException {
//		switch (types[i]) {
//		case Types.CHAR:
//			return rs.getString(i);
//		case Types.VARCHAR:
//			return rs.getString(i);
//		case Types.LONGVARCHAR:
//			return rs.getString(i);
//		case Types.NUMERIC:
//			return rs.getBigDecimal(i);
//		case Types.DECIMAL:
//			return rs.getBigDecimal(i);
//		case Types.BIT:
//			return rs.getBoolean(i);
//		case Types.TINYINT:
//			return rs.getByte(i);
//		case Types.SMALLINT:
//			return rs.getShort(i);
//		case Types.INTEGER:
//			return rs.getInt(i);
//		case Types.BIGINT:
//			return rs.getLong(i);
//		case Types.REAL:
//			return rs.getFloat(i);
//		case Types.FLOAT:
//			return rs.getDouble(i);
//		case Types.DOUBLE:
//			return rs.getDouble(i);
//		case Types.BINARY:
//			return rs.getBytes(i);
//		case Types.VARBINARY:
//			return rs.getBytes(i);
//		case Types.LONGVARBINARY:
//			return rs.getBytes(i);
//		case Types.DATE:
//			return rs.getDate(i);
//		case Types.TIME:
//			return rs.getTime(i);
//		case Types.TIMESTAMP:
//			return rs.getTimestamp(i);
//		case Types.BLOB:
//			Blob blob = rs.getBlob(i);
//			return blob != null ? ConverterUtil.handleBlob(blob) : null;
//		case Types.CLOB:
//			Clob clob = rs.getClob(i);
//			return clob != null ? ConverterUtil.handleClob(clob) : null;
//		case Types.NCLOB:
//			clob = rs.getClob(i);
//			return clob != null ? ConverterUtil.handleClob(clob) : null;
//		case Types.ARRAY:
//			return rs.getArray(i);
//		case Types.REF:
//			return rs.getRef(i);
//		default:
//			return null;
//		}
//	}

protected String replaceFormatSqlOrderBy(String sql) {
int index = sql.lastIndexOf("order by");
if (index > sql.lastIndexOf(")")) {
String sql1 = sql.substring(0, index);
String sql2 = sql.substring(index);
sql2 = sql2
.replaceAll(
"[oO][rR][dD][eE][rR] [bB][yY] [\u4e00-\u9fa5a-zA-Z0-9_.']+((\\s)+(([dD][eE][sS][cC])|([aA][sS][cC])))?(( )*,( )*[\u4e00-\u9fa5a-zA-Z0-9_.']+(( )+(([dD][eE][sS][cC])|([aA][sS][cC])))?)*",
"");
return sql1 + sql2;
}
return sql;
}

}
最后一个了,动态代理类:
public class MyInvocationHandler implements InvocationHandler {
private Object target;
private ICtgCacheManager cache;
private Class<?> clazz;

public MyInvocationHandler(Object target,ICtgCacheManager cache,Class<?> clazz) {
super();
this.target = target;
this.cache=cache;
this.clazz=clazz;
}

@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
//如果是获取代理类则直接执行
if(!"getProxy".equals(method.getName())){
StringBuffer sb = new StringBuffer();
//解析参数拼装成key
for (Object p : args) {
if(p instanceof Object[]){
Object[] params = (Object[]) p;
for (Object string : params) {
if(string instanceof String){
sb.append("#{");
sb.append(string);
sb.append("}");
}
}
}else{
sb.append(p);
}
}
String key = MD5.encode(sb.toString());
String cacheResult = cache.get(key);
Object result=null;
if(cacheResult==null||cacheResult.trim().equals("")){
result = method.invoke(target, args);
if(result!=null){
cache.set(key,JSON.toJSONString(result));
}
}else{
try {
result = JSON.parseObject(cacheResult, clazz);
} catch (Exception e) {
try {
result = JSON.parseArray(cacheResult,clazz);
} catch (Exception e1) {
e1.printStackTrace();
}

}
}
return result;
}else{
Object result = method.invoke(target, args);
return result;
}

}
} 上面是将JSON和实体对象之间互转,应该还有其他更高效的转换方法。

最后控制器直接继承base service 然后this.findxxx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jdbc java cache
相关文章推荐