package com.baidu.unbiz.common.genericdao.mapper; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; import com.baidu.unbiz.common.genericdao.bo.InsertOption; import com.baidu.unbiz.common.genericdao.dao.GenericDao; import com.baidu.unbiz.common.genericdao.operator.Match; import com.baidu.unbiz.common.genericdao.operator.Modify; import com.baidu.unbiz.common.genericdao.operator.Order; import com.baidu.unbiz.common.genericdao.operator.Query; import com.baidu.unbiz.common.genericdao.param.BetweenParam; import com.baidu.unbiz.common.genericdao.param.ExpressionParam; import com.baidu.unbiz.common.genericdao.param.GreaterThanParam; import com.baidu.unbiz.common.genericdao.param.GteParam; import com.baidu.unbiz.common.genericdao.param.IncrParam; import com.baidu.unbiz.common.genericdao.param.LessThanParam; import com.baidu.unbiz.common.genericdao.param.LikeParam; import com.baidu.unbiz.common.genericdao.param.LteParam; import com.baidu.unbiz.common.genericdao.param.NotParam; import com.github.knightliao.apollo.db.bo.BaseObject; /** * @author Darwin(Tianxin) */ public class QueryGenerator<ENTITY extends BaseObject<KEY>, KEY extends Serializable> { /** * @param orMapping * @param genericDao */ public QueryGenerator(ORMapping<ENTITY, KEY> orMapping, GenericDao<KEY, ENTITY> genericDao) { this.orMapping = orMapping; this.dao = genericDao; } private GenericDao<KEY, ENTITY> dao = null; private ORMapping<ENTITY, KEY> orMapping; public Query getSelectQuery(Collection<Match> matches) { // 此处修改以便灵活定义对象 return getMiniSelectQuery(orMapping.getAllColumns(), matches); } public Query getSelectQuery(Collection<Match> matches, Order... orders) { Query query = getSelectQuery(matches); if (orders == null || orders.length == 0) { return query; } // 加入排序 StringBuilder sb = new StringBuilder(query.getSql()); sb.append(" order by "); for (Order entry : orders) { sb.append(entry.getColumn()).append(entry.isAsc() ? " asc" : " desc").append(','); } sb.deleteCharAt(sb.length() - 1); query.setSql(sb.toString()); return query; } public Query getPageQuery(int curPage, int pageSize, Collection<Match> matches, Order... orders) { Query query = getSelectQuery(matches, orders); if (curPage < 0 || pageSize <= 0) { return query; } StringBuilder sb = new StringBuilder(query.getSql()); List<Object> params = query.getParams(); // 设置limit int offset = (curPage) * pageSize; int limit = pageSize; sb.append(" limit ?, ?"); params.add(offset); params.add(limit); query.setSql(sb.toString()); return query; } public Query getMiniSelectQuery(Collection<String> columns, Match... matches) { return getMiniSelectQuery(columns, Arrays.asList(matches)); } /** * 構造一個查詢的SQL語句。當columns為null或size為0時,即為select * ... * * @param columns * @param matches * * @return 下午1:14:54 */ public Query getMiniSelectQuery(Collection<String> columns, Collection<Match> matches) { int matchSize = matches == null ? 0 : matches.size(); int maxSqlLength = matches == null ? 50 : (matchSize + 3) * 10; StringBuilder sb = new StringBuilder(maxSqlLength); // SQL语句和参数列表的构造 sb.append("select "); if (columns == null || columns.size() == 0) { sb.append("*,"); } else { for (String column : columns) { sb.append(column).append(','); } } sb.deleteCharAt(sb.length() - 1); sb.append(" from ").append(dao.getTableName()); if (matchSize == 0) { return new Query(sb.toString(), new ArrayList<Object>(0)); } // 如果有条件 List<Object> params = new ArrayList<Object>(matchSize + 1); appendQuerytoSQL(matches, sb, params); return new Query(sb.toString(), params); } public Query getCountQuery(Match... matches) { return getCountQuery(Arrays.asList(matches)); } public Query getCountQuery(List<Match> matches) { return getMiniSelectQuery(Arrays.asList("count(*)"), matches); } public Query getUpdateQuery(Modify modify, Match... matches) { return getUpdateQuery(Arrays.asList(modify), matches); } public Query getUpdateQuery(List<Modify> modifies, Match... matches) { return getUpdateQuery(modifies, Arrays.asList(matches)); } private Query getUpdateQuery(List<Modify> modifies, List<Match> matches) { StringBuilder sb = new StringBuilder(100); List<Object> params = new ArrayList<Object>(modifies.size() + matches.size()); sb.append("update ").append(dao.getTableName()).append(" set "); appendModifytoSQL(modifies, sb, params); sb.deleteCharAt(sb.length() - 1); appendQuerytoSQL(matches, sb, params); return new Query(sb.toString(), params); } /** * @param matches * * @return 下午3:15:10 created by Darwin(Tianxin) */ public Query getDeleteQuery(Match... matches) { StringBuilder sb = new StringBuilder(100); List<Object> params = new ArrayList<Object>(matches.length); sb.append("delete from ").append(dao.getTableName()); appendQuerytoSQL(Arrays.asList(matches), sb, params); return new Query(sb.toString(), params); } /** * @param modifies * @param sb * @param params */ private void appendModifytoSQL(List<Modify> modifies, StringBuilder sb, List<Object> params) { for (Modify modify : modifies) { sb.append(modify.getColumn()); Object value = modify.getValue(); if (value instanceof IncrParam) { sb.append("=(").append(modify.getColumn()).append("+?),"); params.add(((IncrParam) value).getValue()); } else if (value instanceof ExpressionParam) { sb.append(','); } else { sb.append("=?,"); params.add(value); } } } public Query getUpdateQuery(ENTITY entity) { List<ENTITY> entities = new ArrayList<ENTITY>(0); entities.add(entity); return getUpdateQuery(entities).get(0); } public List<Query> getUpdateQuery(List<ENTITY> entities) { List<Query> queries = new ArrayList<Query>(entities.size()); Set<String> modifiableColumns = orMapping.getModifiableColumns(); for (ENTITY entity : entities) { List<Match> matches = getKeyMatches(entity.getId()); List<Modify> modifies = new ArrayList<Modify>(modifiableColumns.size()); for (String column : modifiableColumns) { Object value = getColumnValue(column, entity); modifies.add(new Modify(column, value)); } queries.add(getUpdateQuery(modifies, matches)); } return queries; } /** * 構造一個create語句的query * * @param generateKey 由數據庫autoincrement生成key,還是應用端指定key * @param quick 時候用快速方式,快速方式無法將自動生成key填充到對象中。一般此參數為false,只有當批量創建,且由數據庫生成key時該處可選。 * @param entities * * @return 下午1:26:37 created by Darwin(Tianxin) */ public Query getCreateQuery(boolean generateKey, boolean quick, ENTITY... entities) { return getCreateQuery(Arrays.asList(entities), generateKey, quick, null); } // FIXME public Query getCreateQuery(boolean generateKey, boolean quick, InsertOption option, ENTITY... entities) { return getCreateQuery(Arrays.asList(entities), generateKey, quick, option); } public Query getCreateQuery(List<ENTITY> entities, boolean generateKey, boolean quick, InsertOption option) { Set<String> allColumns = orMapping.getAllColumns(); Set<String> keyColumn = orMapping.getKeyColumn(); StringBuilder sb = new StringBuilder(entities.size() * 32); List<Object> params = new ArrayList<Object>(allColumns.size() * entities.size()); // bug fixed sb.append("insert " + ((option != null) ? option : "") + " into ").append(dao.getTableName()).append(" ("); StringBuilder sbParams = new StringBuilder((allColumns.size() + 2) * 2); sbParams.append('('); // 如果自動生成key,並且不用快速方式 for (String column : allColumns) { sb.append(column).append(','); sbParams.append("?,"); } sb.deleteCharAt(sb.length() - 1).append(") values"); sbParams.setCharAt(sbParams.length() - 1, ')'); String sParams = sbParams.toString(); if (quick && generateKey) { for (ENTITY entity : entities) { sb.append(sParams).append(','); for (String column : allColumns) { if (keyColumn.contains(column)) { params.add(getKeyColumnValue(column, entity.getId())); } else { params.add(getColumnValue(column, entity)); } } } } else { sb.append(sParams).append(','); for (ENTITY entity : entities) { for (String column : allColumns) { if (keyColumn.contains(column)) { params.add(getKeyColumnValue(column, entity.getId())); } else { params.add(getColumnValue(column, entity)); } } } } return new Query(sb.deleteCharAt(sb.length() - 1).toString(), params); } /** * @param column * @param entity * * @return 上午9:51:49 */ private Object getColumnValue(String column, ENTITY entity) { Method getter = orMapping.getGetter(column); try { return getter.invoke(entity); } catch (Exception e) { throw new RuntimeException(); } } private Object getKeyColumnValue(String column, KEY key) { if (!orMapping.isComplexKey()) { return key; } if (key == null) { return null; } Method getter = orMapping.getGetter(column); try { return getter.invoke(key); } catch (Exception e) { throw new RuntimeException(); } } /** * 获取主键匹配的条件 * * @param id * * @return 上午9:45:33 created by Darwin(Tianxin) */ public List<Match> getKeyMatches(KEY id) { Set<String> keyColumn = orMapping.getKeyColumn(); List<Match> matches = new ArrayList<Match>(keyColumn.size()); for (String column : keyColumn) { Object value = getKeyColumnValue(column, id); matches.add(new Match(column, value)); } return matches; } /** * 将query变成一个查询条件的字符串,放到SQL中 * * @param matches * @param sb * @param params */ public void appendQuerytoSQL(Collection<Match> matches, StringBuilder sb, List<Object> params) { // 如果query为空,则直接返回 if (matches == null || matches.size() == 0) { return; } sb.append(" where "); appendMatches(matches, sb, params); } public void appendMatches(Collection<Match> matches, StringBuilder sb, List<Object> params) { for (Match match : matches) { Object value = match.getValue(); String column = match.getColumn(); if (value == null) { sb.append(column).append(" is null"); } else if (value instanceof LikeParam) { sb.append(column).append(" like ?"); params.add('%' + ((LikeParam) value).getWord() + '%'); } else if (value instanceof BetweenParam) { BetweenParam bp = (BetweenParam) value; Object start = bp.getStart(); Object end = bp.getEnd(); if (start == null && end == null) { sb.append("1!=1"); } else if (start == null) { sb.append(column).append(" <= ?"); params.add(end); } else if (end == null) { sb.append(column).append(" >= ?"); params.add(start); } else { sb.append(column).append(" between ? and ?"); params.add(start); params.add(end); } } else if (value instanceof GteParam) { sb.append(column).append(" >= ?"); params.add(((GteParam) value).getValue()); } else if (value instanceof GreaterThanParam) { sb.append(column).append(" > ?"); params.add(((GreaterThanParam) value).getValue()); } else if (value instanceof LteParam) { sb.append(column).append(" <= ?"); params.add(((LteParam) value).getValue()); } else if (value instanceof LessThanParam) { sb.append(column).append(" < ?"); params.add(((LessThanParam) value).getValue()); } else if (value instanceof ExpressionParam) { sb.append('(').append(column).append(')'); } else { // 如果是取反的参数 boolean reverse = value instanceof NotParam; if (reverse) { value = ((NotParam) value).getValue(); } if (value == null && reverse) { sb.append(column).append(" is not null"); } else if (value instanceof Collection<?>) { Collection<?> coll = (Collection<?>) value; if (coll.size() == 0) { sb.append(reverse ? "1=1" : "1!=1"); } else if (coll.size() == 1) { sb.append(column).append(reverse ? "!=?" : "=?"); params.add(coll.iterator().next()); } else { sb.append(column).append(reverse ? " not in " : " in"); sb.append(connectObjects(coll)); params.addAll(coll); } } else if (value.getClass().isArray()) { Object[] array = (Object[]) value; if (array.length == 0) { sb.append(reverse ? "1=1" : "1!=1"); } else if (array.length == 1) { sb.append(column).append(reverse ? "!=?" : "=?"); params.add(array[0]); } else { sb.append(column).append(reverse ? " not in " : " in"); sb.append(connectObjects(Arrays.asList(array))); for (Object o : array) { params.add(o); } } } else { sb.append(column).append(reverse ? "!=?" : "=?"); params.add(value); } } sb.append(" and "); } sb.delete(sb.length() - 5, sb.length()); } /** * 将数字集合append为( 'n1','n2','n3')这种格式的字符串 * * @param ns * * @return */ public static final String connectObjects(Collection<?> ns) { if (ns == null || ns.size() == 0) { return "()"; } StringBuilder sb = new StringBuilder(ns.size() * 8); int size = ns.size(); for (int i = 0; i < size; i++) { sb.append(",?"); } sb.setCharAt(0, '('); sb.append(')'); return sb.toString(); } public static void main(String[] args) { int i = 0; System.out.println(i += 1); } }