QueryBuilder
Class.createQueryBuilder(entityManager, originSql).build()
public static QueryBuilder createQueryBuilder(EntityManager entityManager, String originSql) {
return new QueryBuilder(entityManager, originSql);
}
public static final class QueryBuilder {
private EntityManager entityManager;
private String originSql;
private List queryParamList = new ArrayList<>();
private List orderParamList = new ArrayList<>();
private QueryBuilder(EntityManager entityManager, String originSql) {
this.entityManager = entityManager;
this.originSql = originSql;
}
public QueryBuilder equals(Object obj, String column) {
QueryParam queryParam = new QueryParam(obj, column, EQUALS);
queryParamList.add(queryParam);
return this;
}
public QueryBuilder special(boolean when, String sql, String[] paramNames, Object[] values) {
QueryParam queryParam = new QueryParam(when, sql, paramNames, values);
queryParamList.add(queryParam);
return this;
}
public QueryBuilder dateRange(DateRangeVO dateRangeVO, String column) {
String[] paramNames = {"dateFromQ", "dateToQ"};
Object[] values = {dateRangeVO.getDateFrom(), dateRangeVO.getDateTo()};
String sql = " and " + column + " between :dateFromQ and :dateToQ ";
return special(dateRangeVO.getDateFrom() != null && dateRangeVO.getDateTo() != null,
sql, paramNames, values);
}
public QueryBuilder like(String obj, String column) {
QueryParam queryParam = new QueryParam(obj, column, LIKE);
queryParamList.add(queryParam);
return this;
}
public QueryBuilder doubleLike(String obj, String column) {
QueryParam queryParam = new QueryParam(obj, column, DOUBLE_LIKE);
queryParamList.add(queryParam);
return this;
}
public QueryBuilder asc(String column, boolean needOrder) {
QueryParam queryParam = new QueryParam(column, ORDER_ASC);
if (needOrder) {
orderParamList.add(queryParam);
}
return this;
}
public QueryBuilder desc(String column, boolean needOrder) {
QueryParam queryParam = new QueryParam(column, ORDER_DESC);
if (needOrder) {
orderParamList.add(queryParam);
}
return this;
}
/*
* to build sql
*/
public Query build() {
StringBuilder sqlBuilder = new StringBuilder(originSql);
for (QueryParam queryParam : queryParamList) {
// Check multipart condition
if (queryParam.values != null && queryParam.paramNames != null) {
if (queryParam.values.length != queryParam.paramNames.length) {
throw new RuntimeException("Cannot build sql, Because the " +
"implanted field lengths do not match");
}
if (queryParam.type.equals(SPECIAL)) {
if (queryParam.specialCondition == null) {
throw new RuntimeException("Cannot build sql, Because the build type is SPECIAL but" +
" condition is null");
}
if (queryParam.specialCondition) {
sqlBuilder.append(OpsuiConstant.SPACE_STR)
.append(queryParam.sql)
.append(OpsuiConstant.SPACE_STR);
}
}
} else {
if (queryParam.value instanceof String) {
if (StringUtils.isNotEmpty((String) queryParam.value)) {
sqlBuilder.append(queryParam.sql);
}
} else {
if (queryParam.value != null) {
sqlBuilder.append(queryParam.sql);
}
}
}
}
if (!orderParamList.isEmpty()) {
sqlBuilder.append(" order by ");
for (int i = 0; i < orderParamList.size(); i++) {
if (i == orderParamList.size() - 1) {
sqlBuilder.append(orderParamList.get(i).sql);
} else {
sqlBuilder.append(orderParamList.get(i).sql).append(", ");
}
}
}
String completeSql = sqlBuilder.toString();
LOG.info("SQLUtil: the automatic sql is: " + completeSql);
Query query = entityManager.createNativeQuery(completeSql);
for (QueryParam queryParam : queryParamList) {
// setParameter for multipart situation
if (queryParam.values != null && queryParam.paramNames != null) {
if (queryParam.values.length != queryParam.paramNames.length) {
throw new RuntimeException("Cannot build sql, Because the " +
"implanted field lengths do not match");
}
if (queryParam.type.equals(SPECIAL)) {
if (queryParam.specialCondition == null) {
throw new RuntimeException("Cannot build sql, Because the build type is SPECIAL but" +
" condition is null");
}
if (queryParam.specialCondition) {
for (int i = 0; i < queryParam.values.length; i++) {
if (queryParam.values[i] instanceof Date) {
query.setParameter(queryParam.paramNames[i],
(Date) queryParam.values[i],
TemporalType.DATE);
} else {
query.setParameter(queryParam.paramNames[i], queryParam.values[i]);
}
}
}
}
} else { // single situation
boolean cond;
if (queryParam.value instanceof String) {
cond = StringUtils.isNotEmpty((String) queryParam.value);
} else {
cond = queryParam.value != null;
}
if (cond) {
if (queryParam.value instanceof Date) {
query.setParameter(queryParam.paramName, (Date) queryParam.value, TemporalType.DATE);
} else {
Object value;
if (queryParam.type.equals(LIKE)) {
value = toLike((String) queryParam.value);
} else if (queryParam.type.equals(DOUBLE_LIKE)) {
value = toDoubleLike((String) queryParam.value);
} else {
value = queryParam.value;
}
query.setParameter(queryParam.paramName, value);
}
}
}
}
return query;
}
} // inner class QueryBuilder
private static final class QueryParam {
Object value;
Object[] values;
String paramName;
String[] paramNames;
String sql;
String type;
String columnName;
Boolean specialCondition;
private QueryParam(Object value, String columnName, String type) {
this.value = value;
this.columnName = columnName;
this.type = type;
this.paramName = randomParamName(columnName);
this.sql = buildSql(columnName, this.paramName, type);
}
/**
* @param type only order_desc or order_asc
*/
private QueryParam(String columnName, String type) {
this.columnName = columnName;
this.type = type;
this.sql = buildOrderSql(columnName, type);
}
private QueryParam(boolean specialCondition, String sql, String[] paramNames, Object[] values) {
this.specialCondition = specialCondition;
this.type = SPECIAL;
this.values = values;
this.sql = sql;
this.paramNames = paramNames;
}
private String randomParamName(String columnName) {
String paramName = columnName.replaceAll("[._]", OpsuiConstant.EMPTY_STR);
return paramName.toLowerCase() + RandomStringUtils.randomAlphabetic(3);
}
private String buildSql(String columnName, String paramName, String type) {
switch (type) {
case EQUALS:
return " and " + columnName + " = " + ":" + paramName;
case LIKE:
case DOUBLE_LIKE:
return " and " + columnName + " like " + ":" + paramName;
default:
throw new RuntimeException("error occurs on SQLUtils: cannot buildSql for column : " + columnName);
}
}
private String buildOrderSql(String columnName, String type) {
switch (type) {
case ORDER_ASC:
return " " + columnName + " asc ";
case ORDER_DESC:
return " " + columnName + " desc ";
default:
throw new RuntimeException("error occurs on SQLUtils: " +
"cannot buildOrderSql for column : " + columnName);
}
}
} // inner class QueryParam