AliasedResultTransformer hibernate的结果集转换

3 篇文章 0 订阅
2 篇文章 0 订阅

基于hql/sql别名转换hibernate的查询结果。不用在担心,使用sql查询返回List<Object[]>需要再次转换。使用hql查询部分栏位也返回List<Object[]>了。使用了reflectasm,这个工具是基于asm的反射工具,比原生的java反射快3倍以上。可以自己去下载https://code.google.com/p/reflectasm/

里面使用了

QueryStatementCache

这就是ConcurrentMap做的一个缓存,可自己简单实现,代码就不贴了。QueryStatement含有一下属性:

this.methodIndexs = statement.getMethodIndexs();
			this.columnAlias = statement.getColumnAlias();
			this.argsTypes = statement.getArgsTypes();
			this.hqlQueryAll = statement.isHqlQueryAll();
			this.sqlQueryAll = statement.isSqlQueryAll();

public class AliasedResultTransformer extends AliasedTupleSubsetResultTransformer {
	private static final Logger logger = LoggerFactory.getLogger(AliasedResultTransformer.class);

	private static final long serialVersionUID = 1L;
	private final Class<?> resultClass;// 结果集类型
	private String[] columnAlias = {};// 查询语句栏位别名
	private ConstructorAccess<?> constructorAccess;// 构造函数访问器
	private MethodAccess methodAccess;// 方法访问器
	private int[] methodIndexs;// 方法索引
	private Class<?>[][] argsTypes;// 栏位别名参数类型/方法参数类型
	private boolean sqlQueryAll = false;// sql查询所有栏位,默认false
	private boolean hqlQueryAll = false;// hql查询所有栏位,默认false
	
	/**
	 * 构造基于sql/hql别名的结果集转换器
	 * 
	 * @param resultClass
	 *            结果集类型
	 * @param sql
	 *            sql/hql语句
	 */
	public <T> AliasedResultTransformer(Class<T> resultClass, String sql, boolean hql) {
		this.resultClass = resultClass;
		this.constructorAccess = AsmUtils.get().createConstructorAccess(resultClass);
		this.methodAccess = AsmUtils.get().createMethodAccess(resultClass);
		
		QueryStatement statement = QueryStatementCache.getInstance().get(sql);
		if (statement != null) {
			this.methodIndexs = statement.getMethodIndexs();
			this.columnAlias = statement.getColumnAlias();
			this.argsTypes = statement.getArgsTypes();
			this.hqlQueryAll = statement.isHqlQueryAll();
			this.sqlQueryAll = statement.isSqlQueryAll();
		} else {
			if (hql) {
				this.hqlQueryAll = ColumnAliasParser.getInstance().isQueryAll(sql);
				if (hqlQueryAll) {
					QueryStatement stmt = new QueryStatement();
					stmt.setHqlQueryAll(hqlQueryAll);
					QueryStatementCache.getInstance().put(sql, stmt);
				}
			} else {
				if (sql.indexOf("*") > 0 && sql.indexOf("count(*)") < 0) {
					this.sqlQueryAll = true;
				}
			}

			if (!hqlQueryAll) {
				if (sqlQueryAll) {
					String[] tempMethodNames = this.methodAccess.getMethodNames();
					Class<?>[][] tempArgsTypes = this.methodAccess.getParameterTypes();
					int length = tempMethodNames.length / 2;
					this.columnAlias = new String[length];
					this.methodIndexs = new int[length];
					this.argsTypes = new Class<?>[length][];
					int j = 0;
					for (int i = 0; i < tempMethodNames.length; i++) {
						String methodName = tempMethodNames[i];
						if (methodName.startsWith("set")) {
							try {
								columnAlias[j] = CamelCaseUtils.toUnderScoreCase(StringUtils.uncapitalize(methodName.substring(3)));
								methodIndexs[j] = methodAccess.getIndex(methodName);
								argsTypes[j] = tempArgsTypes[i];
								j++;
							} catch (IllegalArgumentException e) {
								logger.info("方法[" + methodName + "]不存在,可能是Entity关联栏位。" + e.getMessage());
							}
						}
					}
					putSqlCache(sql);
				} else {// hql/sql基于别名的转换
					this.columnAlias = ColumnAliasParser.getInstance().parseColumnAlias(sql, true);
					String[] tempMethodNames = this.methodAccess.getMethodNames();
					this.methodIndexs = new int[columnAlias.length];
					this.argsTypes = new Class<?>[columnAlias.length][];
					Class<?>[][] tempArgsTypes = this.methodAccess.getParameterTypes();
					for (int i = 0; i < columnAlias.length; i++) {
						for (int j = 0; j < tempMethodNames.length; j++) {
							String methodName = tempMethodNames[j];
							if (methodName.startsWith("set") && columnAlias[i].equals(StringUtils.uncapitalize(methodName.substring(3)))) {
								methodIndexs[i] = this.methodAccess.getIndex(methodName);
								argsTypes[i] = tempArgsTypes[j];
							}
						}
					}
					putSqlCache(sql);
				}
			}
		}

	}

	private void putSqlCache(String sql) {
		QueryStatement stmt = new QueryStatement();
		stmt.setArgsTypes(argsTypes);
		stmt.setColumnAlias(columnAlias);
		stmt.setMethodIndexs(methodIndexs);
		stmt.setHqlQueryAll(hqlQueryAll);
		stmt.setSqlQueryAll(sqlQueryAll);
		QueryStatementCache.getInstance().put(sql, stmt);
	}

	public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
		return false;
	}

	public Object transformTuple(Object[] tuple, String[] aliases) {
		if (hqlQueryAll) {
			return (tuple.length == 1 ? tuple[0] : tuple);
		}

		Object entity = constructorAccess.newInstance();
		for (int i = 0; i < aliases.length; i++) {
			methodAccess.invoke(entity, methodIndexs[i], tuple[i]);
		}
		return entity;
	}

	/**
	 * sql栏位别名对应的类型
	 * 
	 * @return 别名类型
	 * @author yinlei date 2013-6-9 下午7:50:50
	 */
	public Class<?>[][] getArgsTypes() {
		return argsTypes;
	}

	/**
	 * 获取sql中栏位别名数组
	 * 
	 * @return 栏位别名
	 * @author yinlei date 2013-6-9 下午7:50:04
	 */
	public String[] getColumnAlias() {
		return columnAlias;
	}

	public boolean equals(Object o) {
		if (this == o) {
			return true;
		}
		if (o == null || getClass() != o.getClass()) {
			return false;
		}
		AliasedResultTransformer that = (AliasedResultTransformer) o;
		if (!resultClass.equals(that.resultClass)) {
			return false;
		}
		if (!Arrays.equals(columnAlias, that.columnAlias)) {
			return false;
		}
		return true;
	}

	public int hashCode() {
		int result = resultClass.hashCode();
		result = 31 * result
				+ (columnAlias != null ? Arrays.hashCode(columnAlias) : 0);
		return result;
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值