cassandra 数据到Java对象的映射绑定
2017-03-03 10:22
525 查看
类似Hibernate和MyBatis的关系映射,自动帮你将查询数据或是修改的参数进行数据映射和绑定。
支持查询后返回数据ResultSet到Java对象的映射,支持修改、删除、查询之前参数的绑定。
在JavaEntity的命名方式不合规范情况下,可以用Map进行绑定映射。
这种做法可以适用于JDBC的sql result到Java Entity的映射绑定,但需要修改少量的代码。
代码如下:
package com.cnblogs.hoojo.cassar.utils; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.math.BigInteger; import java.net.InetAddress; import java.sql.Timestamp; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import com.datastax.driver.core.BoundStatement; import com.datastax.driver.core.ColumnDefinitions; import com.datastax.driver.core.ColumnDefinitions.Definition; import com.datastax.driver.core.DataType; import com.datastax.driver.core.PreparedStatement; import com.datastax.driver.core.Row; import com.google.common.collect.Maps; /** * <b>function:</b> cassandra 到 JavaEntity 映射转换 * @author hoojo * @createDate 2017-1-19 下午6:20:47 * @file RowMapperUtils.java * @package com.cnblogs.hoojo.cassar.utils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class RowMapperUtils { private static final Logger logger = LoggerFactory.getLogger(RowMapperUtils.class); public static boolean DEBUG = false; public static String LOG_LEVEL = "TRACE"; /** * <b>function:</b> 将查询的Row转换到target 对象中返回 * @author hoojo * @createDate 2017-1-20 下午5:36:20 * @param target 返回Java对象 * @param row {@link Row} * @return 返回Java对象 */ public static <T> T conversion(T target, Row row) { return conversion(target, row, null); } /** * <b>function:</b> 将查询的Row转换到target 对象中返回,row对象存在List、Set集合类型情况 * @author hoojo * @createDate 2017-1-20 下午5:36:20 * @param target 返回Java对象 * @param row {@link Row} * @param genericClass List中存储值 的class类型 * @return 返回Java对象 */ public static <T> T conversion(T target, Row row, Map<String, Class<?>> genericClass) { return conversion(target, row, genericClass, null); } /** * <b>function:</b> 将查询的Row转换到target 对象中返回,row对象存在List、Set、Map集合类型情况 * @author hoojo * @createDate 2017-1-20 下午5:36:20 * @param target 返回Java对象 * @param row {@link Row} * @param valClass List中存储值 的class类型 * @param keyClass List中存储Key 的class类型 * @return 返回Java对象 */ @SuppressWarnings("unchecked") public static <T> T conversion(T target, Row row, Map<String, Class<?>> valClass, Map<String, Class<?>> keyClass) { Class<T> clazz = (Class<T>) target.getClass(); return conversion(clazz, row, valClass, keyClass); } /** * <b>function:</b> 将查询的Row转换到clazz实例对象返回,row对象存在List、Set集合类型情况 * @author hoojo * @createDate 2017-1-20 下午5:36:20 * @param target 返回Java对象 * @param row {@link Row} * @return 返回Java对象 */ public static <T> T conversion(Class<T> clazz, Row row) { return conversion(clazz, row, null); } /** * <b>function:</b> 将查询的Row转换到clazz实例对象返回,row对象存在List、Set集合类型情况 * @author hoojo * @createDate 2017-1-20 下午5:36:20 * @param target 返回Java对象 * @param row {@link Row} * @param genericClass List中存储值 的class类型 * @return 返回Java对象 */ public static <T> T conversion(Class<T> clazz, Row row, Map<String, Class<?>> genericClass) { return conversion(clazz, row, genericClass, null); } public static <T> T transform(T target, Row row, Map<String, Class<?>> valClass, Map<String, Class<?>> keyClass) { ColumnDefinitions cols = row.getColumnDefinitions(); Iterator<Definition> definitionIter = null; definitionIter = cols.iterator(); while (definitionIter.hasNext()) { Definition definition = definitionIter.next(); DataType type = definition.getType(); String columnName = definition.getName(); debug(String.format("列名:%s,列类型:%s", columnName, type)); Object value = getData(row, type, columnName, valClass, keyClass); debug(String.format("列名:%s,取值:%s", columnName, value)); String camelName = camelName(columnName); try { PropertyUtils.setProperty(target, camelName, value); } catch (IllegalAccessException | InvocationTargetException e) { log("设置{}值发生异常:", camelName, e); } catch (NoSuchMethodException ex) { if (camelName.equals(camelName.toLowerCase())) { log("This Class '{}' set '{}' method notfound.", new Object[] { target.getClass().getSimpleName(), camelName } ); } else { try { PropertyUtils.setProperty(target, camelName.toLowerCase(), value); } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException e) { log("设置{}值发生异常:", camelName, e); } catch (NoSuchMethodException e) { log("This Class '{}' set '{}' or set '{}' method notfound.", new Object[] { target.getClass().getSimpleName(), camelName, camelName.toLowerCase() } ); } } } } debug("target: " + target); return target; } /** * <b>function:</b> 将查询的Row转换到clazz实例对象返回,row对象存在List、Set、Map集合类型情况 * @author hoojo * @createDate 2017-1-20 下午5:36:20 * @param target 返回Java对象 * @param row {@link Row} * @param valClass List中存储值 的class类型 * @param keyClass List中存储Key 的class类型 * @return 返回Java对象 */ public static <T> T conversion(Class<T> clazz, Row row, Map<String, Class<?>> valClass, Map<String, Class<?>> keyClass) { T target = BeanUtils.instantiate(clazz); Map<String, PropertyDescriptor> mappedFields = getMappedFields(target.getClass()); ColumnDefinitions cols = row.getColumnDefinitions(); Iterator<Definition> definitionIter = cols.iterator(); while (definitionIter.hasNext()) { Definition definition = definitionIter.next(); DataType type = definition.getType(); String columnName = definition.getName().toLowerCase(); debug(String.format("列名:%s,列类型:%s", columnName, type)); Object value = getData(row, type, columnName, valClass, keyClass); debug(String.format("列名:%s,取值:%s", columnName, value)); if (mappedFields.containsKey(columnName)) { try { mappedFields.get(columnName).getWriteMethod().invoke(target, value); } catch (IllegalAccessException | InvocationTargetException e) { log("设置{}值发生异常:{}", columnName, e); } catch (Exception e) { log("设置{}值发生异常:{}", columnName, e.getMessage()); } } else { log("The target Class '{}' in Column '{}' setter method notFound", clazz.getSimpleName(), columnName); } } debug("target: " + target); return target; } /** * <b>function:</b> 将查询的Row转换到target Map对象中返回 * @author hoojo * @createDate 2017-1-20 下午5:36:20 * @param target 返回Map对象 * @param row {@link Row} * @return 返回Map对象 */ public static <T> Map<String, T> conversion(Map<String, T> target, Row row) { return conversion(target, row, null); } /** * <b>function:</b> 将查询的Row转换到target Map对象中返回,row对象存在List、Set集合类型情况 * @author hoojo * @createDate 2017-1-20 下午5:36:20 * @param target 返回Map对象 * @param row {@link Row} * @param genericClass List中存储值 的class类型 * @return 返回Map对象 */ public static <T> Map<String, T> conversion(Map<String, T> target, Row row, Map<String, Class<?>> genericClass) { return conversion(target, row, genericClass, null); } /** * <b>function:</b> 将查询的Row转换到target Map对象中返回,row对象存在Map集合类型情况 * @author hoojo * @createDate 2017-1-20 下午5:36:20 * @param target 返回Map对象 * @param row {@link Row} * @param valClass MAP、List中存储值 的class类型 * @param keyClass MAP Key 的class类型 * @return 返回Map对象 */ @SuppressWarnings("unchecked") public static <T> Map<String, T> conversion(Map<String, T> target, Row row, Map<String, Class<?>> valClass, Map<String, Class<?>> keyClass) { if (target == null) { target = Maps.newHashMap(); } ColumnDefinitions cols = row.getColumnDefinitions(); Iterator<Definition> definitionIter = cols.iterator(); while (definitionIter.hasNext()) { Definition definition = definitionIter.next(); DataType type = definition.getType(); String columnName = definition.getName().toLowerCase(); debug(String.format("列名:%s,列类型:%s", columnName, type)); Object value = getData(row, type, columnName, valClass, keyClass); debug(String.format("列名:%s,取值:%s", columnName, value)); String camelName = camelName(columnName); if (value != null) { target.put(camelName, (T) value); } else { target.put(camelName, null); } } debug("target: " + target); return target; } /** * <b>function:</b> 为cql PreparedStatement对象自动绑定参数值 * @author hoojo * @createDate 2017-1-20 下午5:33:18 * @param statement PreparedStatement * @param params 参数实体 * @return BoundStatement 已绑定值 */ public static <T> BoundStatement bind(PreparedStatement statement, Map<String, T> bindParam) { BoundStatement boundStatement = null; Map<String, T> params = Maps.newHashMap(bindParam); Set<String> keys = bindParam.keySet(); Iterator<String> iter = keys.iterator(); while (iter.hasNext()) { String key = iter.next(); T val = bindParam.get(key); params.put(key, val); if (!bindParam.containsKey(key.toLowerCase())) { params.put(key.toLowerCase(), val); } key = underscoreName(key).toLowerCase(); if (!bindParam.containsKey(key)) { params.put(key, val); } } Map<String, Object> bindParams = Maps.newLinkedHashMap(); ColumnDefinitions cols = statement.getVariables(); Iterator<Definition> definitionIter = cols.iterator(); while (definitionIter.hasNext()) { Definition definition = definitionIter.next(); DataType type = definition.getType(); String columnName = definition.getName().toLowerCase(); debug(String.format("参数列名:%s,参数列类型:%s", columnName, type)); Object param = null; if (params.containsKey(columnName)) { param = params.get(columnName); } else { log("The target Map does not exist param '{}' value.", columnName); } debug(String.format("参数列名:%s,参数取值:%s", columnName, param)); bindParams.put(columnName, param); } debugCQL(statement.getQueryString(), bindParams); boundStatement = statement.bind(bindParams.values().toArray()); return boundStatement; } /** * <b>function:</b> 为cql PreparedStatement对象自动绑定参数值 * @author hoojo * @createDate 2017-1-20 下午5:33:18 * @param statement PreparedStatement * @param bindEntity 参数实体 * @return BoundStatement 已绑定值 */ public static <T> BoundStatement bind(PreparedStatement statement, T bindEntity) { BoundStatement boundStatement = null; Map<String, Object> params = Maps.newLinkedHashMap(); Map<String, PropertyDescriptor> mappedFields = getMappedFields(bindEntity.getClass()); ColumnDefinitions cols = statement.getVariables(); Iterator<Definition> definitionIter = cols.iterator(); while (definitionIter.hasNext()) { Definition definition = definitionIter.next(); DataType type = definition.getType(); String columnName = definition.getName().toLowerCase(); debug(String.format("参数列名:%s,参数列类型:%s", columnName, type)); Object param = null; if (mappedFields.containsKey(columnName)) { try { param = mappedFields.get(columnName).getReadMethod().invoke(bindEntity); } catch (IllegalAccessException | InvocationTargetException e) { log("设置{}值发生异常:", columnName, e); } } else { log("The target Class '{}' in Column '{}' getter method notFound", bindEntity.getClass().getSimpleName(), columnName); } debug(String.format("参数列名:%s,参数取值:%s", columnName, param)); params.put(columnName, param); } debugCQL(statement.getQueryString(), params); boundStatement = statement.bind(params.values().toArray()); return boundStatement; } /** * <b>function:</b> 调试cql语句,将占位符替换参数值 * @author hoojo * @createDate 2017-1-20 下午5:30:48 * @param queryString cql语句 * @param params 参数 */ private static void debugCQL(String queryString, Map<String, Object> params) { if (DEBUG) { Set<String> keys = params.keySet(); Object[] keyArrays = keys.toArray(); for (int i = 0; i < keys.size(); i++) { queryString = StringUtils.replaceOnce(queryString, "?", MapUtils.getString(params, keyArrays[i], "NULL")); } logger.info("debug cql: {}", queryString); } } private static void debug(String log) { if (DEBUG) { logger.info(log); } } private static void log(String msg, Object... args) { if ("INFO".equalsIgnoreCase(LOG_LEVEL)) { logger.info(msg, args); } else if ("WARN".equalsIgnoreCase(LOG_LEVEL)) { logger.warn(msg, args); } else if ("DEBUG".equalsIgnoreCase(LOG_LEVEL)) { logger.debug(msg, args); } else if ("TRACE".equalsIgnoreCase(LOG_LEVEL)) { logger.trace(msg, args); } else if ("ERROR".equalsIgnoreCase(LOG_LEVEL)) { logger.error(msg, args); } } /** * <b>function:</b> 获取对象的setter方法,并返回下划线命名和全小写命名的Map集合 * @author hoojo * @createDate 2017-1-20 下午5:31:21 * @param clazz 目标对象class * @return Map */ private static Map<String, PropertyDescriptor> getMappedFields(Class<?> clazz) { Map<String, PropertyDescriptor> mappedFields = new HashMap<String, PropertyDescriptor>(); PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(clazz); for (PropertyDescriptor pd : pds) { if (pd.getWriteMethod() != null) { //setUserId->userid,user_id; mappedFields.put(pd.getName().toLowerCase(), pd); String underscoreName = underscoreName(pd.getName()); if (!pd.getName().toUpperCase().equals(underscoreName)) { mappedFields.put(underscoreName.toLowerCase(), pd); } } } return mappedFields; } /** * <b>function:</b> 获取cql 的值 * @author hoojo * @createDate 2017-1-20 下午5:26:24 * @param row {@link Row} * @param type 列类型 * @param columnName 列名 * @param valClass MAP、List中存储值 的class类型 * @param keyClass MAP Key 的class类型 * @return */ private static Object getData(Row row, DataType type, String columnName, Map<String, Class<?>> valClass, Map<String, Class<?>> keyClass) { Object value = null; try { if (type == DataType.bigint()) { value = row.getLong(columnName); } else if (type == DataType.cboolean()) { value = row.getBool(columnName); } else if (type == DataType.blob()) { value = row.getBytes(columnName); } else if (type == DataType.timestamp()) { value = row.getDate(columnName); } else if (type == DataType.decimal()) { value = row.getDecimal(columnName); } else if (type == DataType.cfloat()) { value = row.getFloat(columnName); } else if (type == DataType.inet()) { value = row.getInet(columnName); } else if (type == DataType.cint()) { value = row.getInt(columnName); } else if (type.isCollection() && type.asJavaClass() == List.class) { value = getCollectionData(row, type, columnName, valClass); } else if (type.isCollection() && type.asJavaClass() == Set.class) { value = getCollectionData(row, type, columnName, valClass); } else if (type.isCollection() && type.asJavaClass() == Map.class) { value = getCollectionData(row, type, columnName, valClass, keyClass); } else if (type == DataType.varchar()) { value = row.getString(columnName); } else if (type == DataType.uuid() || type == DataType.timeuuid()) { value = row.getUUID(columnName); } else if (type == DataType.varint()) { value = row.getVarint(columnName); } else if (type == DataType.cdouble()) { value = row.getDouble(columnName); } else if (type == DataType.text()) { value = row.getString(columnName); } } catch (Exception e) { log("获取{}值发生异常:", columnName, e); } if (value == null) { log("Column '{}' Type({}) get cassandra data is NULL.", columnName, type); } return value; } /** * <b>function:</b> 获取cql List集合泛型的值 * @author hoojo * @createDate 2017-1-20 下午5:26:24 * @param row {@link Row} * @param type 列类型 * @param columnName 列名 * @param valClass List Value 的class类型 * @return */ private static Object getCollectionData(Row row, DataType type, String columnName, Map<String, Class<?>> valClass) { Object value = null; Class<?> ofValueType = valClass != null ? valClass.get(columnName) : null; List<DataType> typeArguments = type.getTypeArguments(); if (ofValueType == null) { log("Column TypeArguments convter Error, CQL Type: '{} {}' --> '{} {}(NULL)'", new Object[] { columnName, type, columnName, type.getName() }); } else if (ofValueType != typeArguments.get(0).asJavaClass()) { log("Column TypeArguments convter Error, CQL Type: '{} {}({})' --> '{} {}({})'", new Object[] { columnName, type, typeArguments.get(0).asJavaClass(), columnName, valueOf(type.asJavaClass(), ofValueType), ofValueType }); } else if (type.asJavaClass() == List.class) { value = row.getList(columnName, ofValueType); } else if (type.asJavaClass() == Set.class) { value = row.getSet(columnName, ofValueType); } return value; } /** * <b>function:</b> 获取cql MAP集合泛型的值 * @author hoojo * @createDate 2017-1-20 下午5:26:24 * @param row {@link Row} * @param type 列类型 * @param columnName 列名 * @param valClass MAP Value 的class类型 * @param keyClass MAP Key 的class类型 * @return */ private static Object getCollectionData(Row row, DataType type, String columnName, Map<String, Class<?>> valClass, Map<String, Class<?>> keyClass) { Object value = null; Class<?> ofKeyType = keyClass != null ? keyClass.get(columnName) : null; Class<?> ofValueType = valClass != null ? valClass.get(columnName) : null; List<DataType> typeArguments = type.getTypeArguments(); if (ofValueType == null && ofKeyType == null) { log("Column TypeArguments convter Error, CQL Type: '{} {}' --> '{} {}<NULL, NULL>'", new Object[] { columnName, type, columnName, type.getName() }); } else if (ofValueType == null) { log("Column TypeArguments convter Error, CQL Type: '{} {}' --> '{} {}<{}, NULL>'", new Object[] { columnName, type, columnName, type.getName(), valueOf(ofKeyType) }); } else if (ofKeyType == null) { log("Column TypeArguments convter Error, CQL Type: '{} {}' --> '{} {}<NULL, {}>'", new Object[] { columnName, type, columnName, type.getName(), valueOf(ofValueType) }); } else if (ofKeyType != typeArguments.get(0).asJavaClass() || ofValueType != typeArguments.get(1).asJavaClass()) { log("Column TypeArguments convter Error, CQL Type: '{} {} (<{}, {}>)' --> '{} {}(<{}, {}>)'", new Object[] { columnName, type, typeArguments.get(0).asJavaClass(), typeArguments.get(1).asJavaClass(), columnName, valueOf(Map.class, ofValueType, ofKeyType), ofKeyType, ofValueType }); } else { value = row.getMap(columnName, ofKeyType, ofValueType); } return value; } /** * <b>function:</b> 转换为下划线命名方式 * @author hoojo * @createDate 2017-1-20 下午5:24:50 */ public static String underscoreName(String name) { StringBuilder result = new StringBuilder(); if (name != null && name.length() > 0) { // 将第一个字符处理成大写 result.append(name.substring(0, 1).toUpperCase()); // 循环处理其余字符 for (int i = 1; i < name.length(); i++) { String s = name.substring(i, i + 1); // 在大写字母前添加下划线 if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0))) { result.append("_"); } // 其他字符直接转成大写 result.append(s.toUpperCase()); } } return result.toString(); } /** * <b>function:</b> 驼峰式命名方式 * @author hoojo * @createDate 2017-1-20 下午5:25:09 */ public static String camelName(String name) { StringBuilder sb = new StringBuilder(); 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 (sb.length() == 0) { // 第一个驼峰片段,全部字母都小写 sb.append(camel.toLowerCase()); } else { // 其他的驼峰片段,首字母大写 sb.append(camel.substring(0, 1).toUpperCase()); sb.append(camel.substring(1).toLowerCase()); } } return sb.toString(); } /** * <b>function:</b> java class转换到cql类型 * @author hoojo * @createDate 2017-1-20 下午5:24:09 * @param clazz Class * @return {@link DataType} */ private static DataType valueOf(Class<?> clazz) { if (clazz == null) { return DataType.custom("NULL"); } if (clazz == long.class || clazz == Long.class) { return DataType.bigint(); } if (clazz == boolean.class || clazz == Boolean.class) { return DataType.cboolean(); } if (clazz == Byte.class || clazz == byte.class) { return DataType.blob(); } if (clazz == Date.class || clazz == Timestamp.class) { return DataType.timestamp(); } if (clazz == BigDecimal.class) { return DataType.decimal(); } if (clazz == float.class || clazz == Float.class) { return DataType.cfloat(); } if (clazz == InetAddress.class) { return DataType.inet(); } if (clazz == int.class || clazz == Integer.class) { return DataType.cint(); } if (clazz == String.class) { return DataType.varchar();// text(); } if (clazz == UUID.class) { return DataType.uuid(); // timeuuid(); } if (clazz == BigInteger.class) { return DataType.varint(); } log("Class '{}' unknow DataType in cassandra.", clazz); return DataType.custom("unknow"); } /** * <b>function:</b> 转换集合list、set到cql类型 * @author hoojo * @createDate 2017-1-20 下午5:22:43 * @param clazz java class * @param valueClass 集合值存储类型class * @param keyClass 集合键存储类型class * @return DataType */ public static DataType valueOf(Class<?> clazz, Class<?> valueClass, Class<?> keyClass) { if (clazz == List.class) { return DataType.list(valueOf(valueClass)); } if (clazz == Set.class) { return DataType.set(valueOf(valueClass)); } if (clazz == Map.class) { return DataType.map(valueOf(keyClass), valueOf(valueClass)); } log("Class '{}' unknow DataType in cassandra.", clazz); return DataType.custom("unknow"); } /** * <b>function:</b> 转换集合list、set到cql类型 * @author hoojo * @createDate 2017-1-20 下午5:22:43 * @param clazz java class * @param valueClass 集合存储类型class * @return DataType */ private static DataType valueOf(Class<?> clazz, Class<?> valueClass) { return valueOf(clazz, valueClass, null); } }
相关文章推荐
- 从XML到Java代码的数据绑定之对象
- Json数据解析----------Gson用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库
- XML到Java代码的数据绑定之对象
- springmvc form多对象映射 数据绑定 多对象绑定
- Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。可以将一个 JSON 字符串转成一个 Java 对象,或者反过来。
- 解析Java的Jackson库中对象的序列化与数据泛型绑定
- 实现Castor数据绑定,把 Java 对象绑定到 SQL 数据库
- java的一段对象数据类型映射的代码
- Springmvc-将前端数据映射成JAVA对象接收实例
- JAVA反射机制示例,读取excel数据映射到JAVA对象中
- XML到Java代码的数据绑定之对象
- jface databinding:可多选的widget List组件selection项目与java.util.List对象的双向数据绑定
- 使用Struts 2将客户端JSON数据映射为服务器端Java对象
- 使用Struts 2将客户端JSON数据映射为服务器端Java对象
- 从XML到Java代码的数据绑定之对象
- Extraction应用构建平台应用基础(八)------数据类型和Java对象的映射关系篇
- 2006-07-28 Java的常用包,"=="和"equals"的用法,基本数据类型与引用类型,对象的克隆
- 教您如何用Zeus实现XML-Java的数据绑定
- Java-XML数据绑定工具大比拼
- ArrayList中的数据排序--java对象排序