Hibernate命名查询复制粘贴

时间:2011-02-19 13:08:31

标签: java hibernate hql

在我的.hbm.xml中有两个查询。第一个检索表中的记录数:

<query name="Airframe.SearchCount"><![CDATA[
    select
        count(*)
    from
        AirframeBean as a inner join
        a.manufacturer as m
    where
        m.name like :manufacturer and
        a.description like :description and
        ((a.percentSize <= :sizeMax and
        a.percentSize >= :sizeMin) or
        a.percentSize is null) and
        ((a.wingSpanInches <= :spanMax and
        a.wingSpanInches >= :spanMin) or
        a.wingSpanInches is null) and
        ((a.recommendedAuwMinLbs <= :auwMax and
        a.recommendedAuwMaxLbs >= :auwMin) or
        a.recommendedAuwMaxLbs is null)
]]></query>

第二个使用偏移和限制逐页获取数据:

<query name="Airframe.SearchData"><![CDATA[
    select
        a
    from
        AirframeBean as a inner join
        a.manufacturer as m
    where
        m.name like :manufacturer and
        a.description like :description and
        ((a.percentSize <= :sizeMax and
        a.percentSize >= :sizeMin) or
        a.percentSize is null) and
        ((a.wingSpanInches <= :spanMax and
        a.wingSpanInches >= :spanMin) or
        a.wingSpanInches is null) and
        ((a.recommendedAuwMinLbs <= :auwMax and
        a.recommendedAuwMaxLbs >= :auwMin) or
        a.recommendedAuwMaxLbs is null)
]]></query>

查询几乎相同。唯一的区别是第一个以select count(*)开头,第二个以select a开头。有没有办法避免复制粘贴?

更新 主要问题是我需要Hibernate在启动时验证模式,映射和HQL查询。

4 个答案:

答案 0 :(得分:4)

您可以这样做: -

命名查询

#SELECTOR#是您的Java代码必须替换的占位符。

<query name="Airframe"><![CDATA[
    select
        #SELECTOR#
    from
        AirframeBean as a inner join
        a.manufacturer as m
    where
        m.name like :manufacturer and
        a.description like :description and
        ((a.percentSize <= :sizeMax and
        a.percentSize >= :sizeMin) or
        a.percentSize is null) and
        ((a.wingSpanInches <= :spanMax and
        a.wingSpanInches >= :spanMin) or
        a.wingSpanInches is null) and
        ((a.recommendedAuwMinLbs <= :auwMax and
        a.recommendedAuwMaxLbs >= :auwMin) or
        a.recommendedAuwMaxLbs is null)
]]></query>

Hibernate代码

public Long searchCount() {
    String sql = getQueryString("Airframe").replace("#SELECTOR#", "count(*)");
    return (Long) session.createSQLQuery(sql, args...).uniqueResult();
}

@SuppressWarnings("unchecked")
public List<AirframeBean> getAirframeBeans() {
    String sql = getQueryString("Airframe").replace("#SELECTOR#", "a");
    return session.createSQLQuery(sql, args...).list();
}

private String getQueryString(String namedQuery) {
    return session.getNamedQuery(namedQuery).getQueryString();
}

答案 1 :(得分:1)

一个想法是,如果您决定升级到程序/注释驱动的持久性。一旦您将查询作为java HQL字符串查询或DetachedStatement促进重用是轻而易举的事。考虑使用HQL的方案,您可以通过以下方式获得所需的效果:

String hql = ... 
hql = hql.replace("count(*)", "a");

或者:

String hql = "from ...";
String q1 = "select count(*) " + hql;
String q2 = "select a " + hql;

另见How this SQL Query in hbm.xml file can be written in source code?

答案 2 :(得分:0)

另一个想法是使用Criteria API来管理分页而不是命名查询。 使用hibernate Criteria API,您可以使用方法setFirstResult()和setMaxResult()来定义要为表加载的数据组。

答案 3 :(得分:-1)

Criteria API是一种使用hibernate创建查询的不同方式,对于分页而言非常有用。

使用代码的一个例子是:

      
  Criteria crit = session.createCriteria(AirframeBean.class);
  crit.add(Restrictions.like("name", "manufacturer"));
  crit.add(Restrictions.like("description", "yourDescription"));
  crit.add(Restrictions.between("percentSize", "sizeMin", "sizeMax"));

  ecc....

  crit.setMaxResults(maxResults);
  crit.setFirstResult(firstResult);
  List result = crit.list()

要添加条件AND或OR,您可以使用:Restrictions.disjunction();或Restrictions.conjunction();

通过这种方式,您只使用java代码而不使用xml文件来管理和编写动态查询。