码迷,mamicode.com
首页 > 数据库 > 详细

通过Hql、Sql生成Hibernate CountQuery 字符串

时间:2015-02-06 13:18:17      阅读:218      评论:0      收藏:0      [点我收藏+]

标签:

当我们在写Hibernate Orm组件的时候,经常会遇到分页查询这种操作,分页查询的原理不在熬述,比较重要的一点是需要计算查询的总数count,大部分人还是采用传统的hql/sql字符串截取或者拼接等方式实现。下面给出的代码是通过字符串模板、正则匹配等方式实现的,直接上代码:

public class QueryTemplateUtil {

 public static final String COUNT_QUERY_STRING = "select count(%s) from %s x";
 public static final String DELETE_ALL_QUERY_STRING = "delete from %s x";

 private static final String COUNT_REPLACEMENT_TEMPLATE = "select count(%s) $5$6$7";
 private static final String SIMPLE_COUNT_VALUE = "$2";
 private static final String COMPLEX_COUNT_VALUE = "$3$6";

 private static final Pattern COUNT_MATCH;

 private static final String IDENTIFIER = "[\\p{Alnum}._$]+";
 private static final String IDENTIFIER_GROUP = String.format("(%s)",
   IDENTIFIER);

 private static final String EQUALS_CONDITION_STRING = "%s.%s = ?";

 static {

  StringBuilder builder = new StringBuilder();
  builder.append("(?<=from)"); // from as starting delimiter
  builder.append("(?: )+"); // at least one space separating
  builder.append(IDENTIFIER_GROUP); // Entity name, can be qualified (any
  builder.append("(?: as)*"); // exclude possible "as" keyword
  builder.append("(?: )+"); // at least one space separating
  builder.append("(\\w*)"); // the actual alias


  builder = new StringBuilder();
  builder.append("(select\\s+((distinct )?(.+?)?)\\s+)?(from\\s+");
  builder.append(IDENTIFIER);
  builder.append("(?:\\s+as)?\\s+)");
  builder.append(IDENTIFIER_GROUP);
  builder.append("(.*)");

  COUNT_MATCH = compile(builder.toString(), CASE_INSENSITIVE);
 }

 /**
  * Private constructor to prevent instantiation.
  */
 private QueryTemplateUtil() {

 }

 /**
  * getCountQueryString:根据实体名称,count字段,查询条件生成count查询字符串
  * <p>
  * <b>例如:</b>{@code entityName="User"},{@code countQueryPlaceHolder="*"},
  * {@code conditionAttributes=["name","sex"]},生成的countQueryString是:
  * </p>
  * <p>
  * {@code select count(*) from User x where x.name=? and x.sex=?}
  * </p>
  * 
  * @Title: getCountQueryString
  * @param entityName
  *            实体名称,不允许{@literal null}或者{@literal empty}
  * @param countQueryPlaceHolder
  *            count查询占位字段,不允许{@literal null}或者{@literal empty}
  * @param conditionAttributes
  *            查询条件字段
  * @return String
  */
 public static String getCountQueryString(String entityName,
   String countQueryPlaceHolder, Iterable<String> conditionAttributes) {
  Assert.hasText(entityName, "实体名称不允许为null或empty!");
  StringBuilder sb = new StringBuilder(String.format(COUNT_QUERY_STRING,
    countQueryPlaceHolder, entityName));
  sb.append(" WHERE ");

  if (conditionAttributes != null) {
   for (String conditionAttribute : conditionAttributes) {
    sb.append(String.format(EQUALS_CONDITION_STRING, "x",
      conditionAttribute));
    sb.append(" AND ");
   }
  }

  sb.append("1 = 1");
  return sb.toString();
 }

 /**
  * getCountQueryString:根据实体名称,生成count查询字符串
  * <p>
  * <b>注意:</b>count占位字符默认为{@literal *},不带查询条件
  * </p>
  * 
  * @Title: getCountQueryString
  * @param entityName
  *            实体名称,不允许{@literal null}或者{@literal empty}
  * @return {@code select count(*) from SomeEntity x }
  */
 public static String getCountQueryString(String entityName) {
  return getCountQueryString(entityName, "*", null);
 }

 /**
  * getCountQueryString:根据实体名称、查询条件生成count查询字符串
  * 
  * @Title: getCountQueryString
  * @param entityName
  *            实体名称,不允许{@literal null}或者{@literal empty}
  * @param conditionAttributes
  *            查询条件字段
  * @return {@code select count(*) from SomeEntity x where condition1=? and condition2=? and 1=1}
  */
 public static String getCountQueryString(String entityName,
   Iterable<String> conditionAttributes) {
  return getCountQueryString(entityName, "*", conditionAttributes);

 }

 /**
  * getQueryString:通过实体名称与查询字符串模板,创建查询字符串
  * <p>
  * <b>参见:</b>{@link org.mk.mini.orm.util.DELETE_ALL_QUERY_STRING}
  * </p>
  * 
  * @Title: getQueryStringByTemplate
  * @param template
  *            查询字符串模板
  * @param entityName
  *            实体名称
  * @return 查询字符串
  */
 public static String getQueryStringByTemplate(String template,
   String entityName) {

  Assert.hasText(entityName, "实体名称不允许为null或empty!");

  return String.format(template, entityName);
 }

 

 /**
  * createCountQueryFor:通过给定的原始sql或hql创建count查询字符串.
  * 
  * @Title: createCountQueryFor
  * @param originalQuery
  *            原始查询字符串,支持sql与hql 不能为 {@literal null} 或者 {@literal empty}
  * @return
  */
 public static String createCountQueryFor(String originalQuery) {

  Assert.hasText(originalQuery, "查询字符串不允许为null或empty");

  Matcher matcher = COUNT_MATCH.matcher(originalQuery);
  String variable = matcher.matches() ? matcher.group(4) : null;
  boolean useVariable = ExtraStringUtils.hasText(variable)
    && !variable.startsWith("new")
    && !variable.startsWith("count(");

  return matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE,
    useVariable ? SIMPLE_COUNT_VALUE : COMPLEX_COUNT_VALUE));
 }
}

 

实例就不用写了,注释已经写的很清楚,关于Assert和ExtraStringUtils只是做了断言判断与字符串判断,需要copy该代码的同学们可以改造一下,写的不好,请指正。

通过Hql、Sql生成Hibernate CountQuery 字符串

标签:

原文地址:http://blog.csdn.net/mark0614/article/details/43562299

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!