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