hibernate结果集转换器ResultTransformer。基于别名实现

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 String[] methodNames;// 方法名
	private int[] methodIndexs;// 方法索引
	private Class<?>[][] argsTypes;// 栏位别名参数类型/方法参数类型
	private String sql;// 查询语句
	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) {
//		if (sql.indexOf("select new") > -1) {
//			throw new IllegalStateException("hql使用了select new JavaBean() from...方式,就不需要设置query.setResultTransformer()了。");
//		}
//		if (resultClass == null) {
//			throw new IllegalArgumentException("resultClass cannot be null");
//		}
		this.resultClass = resultClass;
		this.sql = sql;
		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 (sql.indexOf("*") > 0 && sql.indexOf("count(*)") < 0) {
				this.sqlQueryAll = true;
			} else {
				this.hqlQueryAll = ColumnAliasParser.getInstance().isQueryAll(sql);
				if (hqlQueryAll) {
					QueryStatement stmt = new QueryStatement();
					stmt.setHqlQueryAll(hqlQueryAll);
					QueryStatementCache.getInstance().put(sql, stmt);
				}
			}

			if (!hqlQueryAll && !sqlQueryAll) {// 不是查询所有栏位,需要重新解析sql/hql
				this.columnAlias = ColumnAliasParser.getInstance().parseColumnAlias(sql, true);
				String[] tempMethodNames = this.methodAccess.getMethodNames();
				this.methodNames = new String[columnAlias.length];
				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)))) {
							methodNames[i] = methodName;
							methodIndexs[i] = this.methodAccess.getIndex(methodName);
							argsTypes[i] = tempArgsTypes[j];
						}
					}
				}

				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);
		} else if (sqlQueryAll) {
			this.columnAlias = aliases;

			// 没有解析过,将解析
			if (methodIndexs == null || methodIndexs.length <= 0
					|| argsTypes == null || argsTypes.length <= 0) {
				this.methodIndexs = new int[columnAlias.length];
				this.argsTypes = new Class<?>[columnAlias.length][];
				Class<?>[][] tempArgsTypes = this.methodAccess.getParameterTypes();
				for (int i = 0; i < aliases.length; i++) {
					String methodName = "set" + CamelCaseUtils.toCapitalizeCamelCase(aliases[i]);
					try {
						methodIndexs[i] = methodAccess.getIndex(methodName);
						argsTypes[i] = tempArgsTypes[methodIndexs[i]];
					} catch (IllegalArgumentException e) {
						logger.info("方法[" + methodName + "]不存在,可能是Entity关联栏位。" + e.getMessage());
					}
				}
				QueryStatement stmt = new QueryStatement();
				stmt.setArgsTypes(argsTypes);
				stmt.setColumnAlias(columnAlias);
				stmt.setMethodIndexs(methodIndexs);
				stmt.setHqlQueryAll(hqlQueryAll);
				stmt.setSqlQueryAll(sqlQueryAll);
				QueryStatementCache.getInstance().put(sql, stmt);
			}
		}

		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;
	}
}


里面使用了reflectasm,以及基于reflectasm的封装工具。

public class ColumnAliasParser {
    private static ConcurrentMap<String, String[]> aliasCache = new ConcurrentHashMap<String, String[]>();
    private static ColumnAliasParser instance = new ColumnAliasParser();
    
    private ColumnAliasParser() {
            
    }
    
    /**
     * 获取ColumnAliasParser单例
     * @return ColumnAliasParser单例
     * @author yinlei
     * date 2013-6-12 下午10:22:04
     */
    public static ColumnAliasParser getInstance() {
        return instance;
    }
    
    /**
     * 解析sql/hql字段别名,如果没有别名返回字段名
     * @param sql sql/hql语句
     * @param isCache 是否缓存
     * @return 别名String数组
     */
    public String[] parseColumnAlias(String sql, boolean isCache) {
		if (isCache) {
			String[] columnAlias = aliasCache.get(sql);
			if (columnAlias == null || columnAlias.length == 0) {
				columnAlias = aliasParser(sql);
				aliasCache.put(sql, columnAlias);
			}
			return columnAlias;
		} else {
			return aliasParser(sql);
		}
    }

    private String[] aliasParser(String sql) {
		int from = sql.indexOf("select") + 6;
		int to = sql.indexOf("from");
		String sqlAlias = sql.substring(from, to);

		String[] columns = StringUtils.split(sqlAlias, ",");
		String[] columnAlias = new String[columns.length];
		int i = 0;
		for (String alias : columns) {
			String[] temp = StringUtils.split(alias, " ");
			String t = temp[temp.length - 1].trim();
			if (t.contains(".")) {
				t = t.substring(t.indexOf(".") + 1);
			}
			columnAlias[i] = t;
			i++;
		}
		return columnAlias;
    }
    
    /**
     * 删除指定sql的别名缓存
     * @param sqlKey sql语句
     * @return sqlKey对应的以前的值
     * @author yinlei
     * date 2013-6-12 下午10:18:11
     */
    public String[] clear(String sqlKey) {
        return aliasCache.remove(sqlKey);
    }
    
    /**
     * 更新sql别名缓存值
     * @param sqlKey sql语句
     * @param sqlAlias sql别名数组
     * @return sqlKey对应的以前的值
     * @author yinlei
     * date 2013-6-12 下午10:18:19
     */
    public String[] replace(String sqlKey, String[] sqlAlias) {
        return aliasCache.replace(sqlKey, sqlAlias);
    }
    
    public boolean isQueryAll(String sql) {
		String[] columnAlias = ColumnAliasParser.getInstance().parseColumnAlias(sql, true);

		int start = sql.indexOf("from") + 4;
		int end = sql.indexOf("where");
		String tableNames = null;
		if (end == -1) {
			tableNames = sql.substring(start);
		} else {
			tableNames = sql.substring(start, end);
		}

		String[] tables = StringUtils.split(tableNames, ",");

		boolean queryAll = false;
		label: for (int i = 0; i < tables.length; i++) {
			String[] temp = StringUtils.split(tables[i], " ");
			String t = temp[temp.length - 1].trim();
			for (String alias : columnAlias) {
				if (t.equals(alias)) {
					queryAll = true;
					break label;
				}
			}
		}
//		if (queryAll) {
//			ColumnAliasParser.getInstance().clear(sql);
//		}
		return queryAll;
    }
    
    public static void main(String[] aa) {
		String sql = "select   new Subject() from Subject s where s.subjectCode = ?1";
		long da = System.currentTimeMillis();
		ColumnAliasParser.getInstance().isQueryAll(sql);

		System.out.println(System.currentTimeMillis() - da);
            
    }
    
}

hibernate的查询的封装:

/**
	 * 查询VO Bean List,一般用于多实体连接<br>
	 * 1、使用select new查询VO Bean,select new com.eecn.warehouse.api.model.AUser(i.sbillno,u) from Inventory i, User u where i.scustomerno = u.userAccount<br>
	 * 2、使用别名查询VO Bean,select i.sbillno as id,u as user from Inventory i, User u where i.scustomerno = u.userAccount,VO要有对应的构造函数<br>
	 * 3、如果不使用别名,返回List<Object[]>,对于2中的结果返回{“sbillno”, User}<br>
	 * 4、查询PO也是可以的,但是建议使用{@link #getEntityListByHql(String, Object...)}代替<br>
	 * @param hql
	 * @param resultClass
	 * @param values
	 * @return
	 */
    public <E> List<E> getListByHql(String hql, Class<E> resultClass, Object... values){
        //hql = "select new com.eecn.warehouse.api.model.User(u.id,u.userAccount,u.userName) from User u ";  
    	//hql = "select u from User u";
    	//hql = "select i.sbillno as id,u as user from Inventory i, User u where i.scustomerno = u.userAccount order by i.dindate desc";
    	//hql = "select i.sbillno,u from Inventory i, User u where i.scustomerno = u.userAccount order by i.dindate desc";
    	//hql = "select new com.eecn.warehouse.api.model.Address(u.id,u.userAccount,u.userName) from User u";
    	//hql = "select new com.eecn.warehouse.api.model.AUser(i.sbillno,u) from Inventory i, User u where i.scustomerno = u.userAccount order by i.dindate desc";
    	
		Query query = createQuery(hql, values);
//		HQLQueryPlan hqlQueryPlan = getHqlQueryPlan(hql);
//		String[] aliases = hqlQueryPlan.getReturnMetadata().getReturnAliases();
//		String[] sqls = hqlQueryPlan.getSqlStrings();
		if (resultClass != null && hql.indexOf("select new") < 0) {
			query.setResultTransformer(new AliasedResultTransformer(AUser.class, hql));
		}
		//System.out.println(Arrays.toString(query.getReturnAliases()));
		List<E> list = query.list();
		if (list == null) {
			list = Collections.emptyList();
		}
		
		return list;
    }
/**
	 * 查询PO Bean List<br>
	 * 1、查询全部栏位,select u from User u where...<br>
	 * 2、查询部分栏位,select new User(u.id,u.name) from User u where...<br>
	 * 3、查询部分栏位,则返回List<Object[]>这个情况建议使用{@link #getListByHql(String, Class, Object...)}可以直接返回JavaBean
	 */
	public List<T> getEntityListByHql(String hql, Object... values) {
		Query query = createQuery(hql, values);
		List<T> list = query.list();
		if (list == null) {
			list = Collections.emptyList();
		}
		return list;
	}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值