代码之家  ›  专栏  ›  技术社区  ›  AndrewB

WHERE子句作为参数

  •  1
  • AndrewB  · 技术社区  · 16 年前

    在转换遗留应用程序时,我们需要将命名查询转换为nhibernate。问题是正在设置WHERE子句。

    这是地图

    <resultset name="PersonSet">
    <return alias="person" class="Person">
      <return-property column="id" name="Id" />
      <return-property column="ssn" name="Ssn" />
      <return-property column="last_name" name="LastName" />
      <return-property column="first_name" name="FirstName"/>
      <return-property column="middle_name" name="MiddleName" />
    </return>
    </returnset>
    
    <sql-query name="PersonQuery" resultset-ref="PersonSet" read-only="true" >
      <![CDATA[
      SELECT
      person.ID as {person.Id},
      person.SSN as {person.Ssn},
      person.LAST_NAME as {person.LastName},
      person.MIDDLE_NAME as {person.MiddleName},
      person.FIRST_NAME as {person.FirstName},
      FROM PERSONS as person
      where :value
      ]]>
    </sql-query>
    

    C代码:

    String query = "person.LAST_NAME = 'Johnson'";
    HibernateTemplate.FindByNamedQueryAndNamedParam("PersonQuery", "value", query);
    

    错误:

    哪里?];errorcode[];在“@p0”附近需要条件的上下文中指定的非布尔类型的表达式。

    3 回复  |  直到 9 年前
        1
  •  2
  •   jitter    16 年前

    这不起作用,因为你试图更换 :value 具有 "person.LAST_NAME = 'Johnson'" 希望查询变成

    SELECT person.ID, person.SSN, person.LAST_NAME, person.MIDDLE_NAME, person.FIRST_NAME
    FROM PERSONS as person
    where person.LAST_NAME = 'Johnson'
    

    这行不通。您只能动态替换“Johnson”部分,而不能替换整个条件。因此真正产生的是

    SELECT person.ID, person.SSN, person.LAST_NAME, person.MIDDLE_NAME, person.FIRST_NAME
    FROM PERSONS as person
    where 'person.LAST_NAME = \'Johnson\''
    

    这显然不是WHERE部分的有效条件,因为只有一个文本,但没有要将字段与之比较的列和运算符。

    如果你只需要与 person.LAST_NAME 将XML SQL查询重写为

    <sql-query name="PersonQuery" resultset-ref="PersonSet" read-only="true" >
      <![CDATA[
      SELECT
      ...
      FROM PERSONS as person
      where person.LAST_NAME = :value
      ]]>
    </sql-query>
    

    在C代码集中

    String query = "Johnson";
    

    如果需要一次按不同的列甚至多个列动态筛选,请使用筛选。例如,这样(我对您的Hibernate映射文件做了一些假设)

    <hibernate-mapping>
      ...
      <class name="Person">
        <id name="id" type="int">
          <generator class="increment"/>
        </id>
        ...
        <filter name="ssnFilter" condition="ssn = :ssnValue"/>
        <filter name="lastNameFilter" condition="lastName = :lastNameValue"/>
        <filter name="firstNameFilter" condition="firstName = :firstNameValue"/>
        <filter name="middleNameFilter" condition="middleName = :middleNameValue"/>
      </class>
      ...
      <sql-query name="PersonQuery" resultset-ref="PersonSet" read-only="true" >
      ...
        FROM PERSONS as person
      ]]>
      </sql-query>
      <!-- note the missing WHERE clause in the PersonQuery -->
      ...
      <filter-def name="ssnFilter">
        <filter-param name="ssnValue" type="int"/>
      </filter-def>
      <filter-def name="lastNameFilter">
        <filter-param name="lastNameValue" type="string"/>
      </filter-def>
      <filter-def name="middleNameFilter">
        <filter-param name="midlleNameValue" type="string"/>
      </filter-def>
      <filter-def name="firstNameFilter">
        <filter-param name="firstNameValue" type="string"/>
      </filter-def>
    </hibernate-mapping>
    

    现在在您的代码中,您应该能够做到

    String lastName = "Johnson";
    String firstName = "Joe";
    
    //give me all persons first
    HibernateTemplate.FindByNamedQuery("PersonQuery");
    
    //just give me persons WHERE FIRST_NAME = "Joe" AND LAST_NAME = "Johnson"
    Filter filter = HibernateTemplate.enableFilter("firstNameFilter");
    filter.setParameter("firstNameValue", firstName);
    filter = HibernateTemplate.enableFilter("lastNameFilter");
    filter.setParameter("lastNameValue", lastName);
    HibernateTemplate.FindByNamedQuery("PersonQuery");
    
    //oh wait. Now I just want all Johnsons
    HibernateTemplate.disableFilter("firstNameFilter");
    HibernateTemplate.FindByNamedQuery("PersonQuery");
    
    //now again give me all persons
    HibernateTemplate.disableFilter("lastNameFilter");
    HibernateTemplate.FindByNamedQuery("PersonQuery");
    

    如果您还需要更多的动态查询(例如,甚至更改运算符(,)。=,如,>、<、…)或必须逻辑地组合限制(其中lastname=“foo” firstname“=“foobar”)那么现在是时候研究

    Hibernate Criteria API

        2
  •  0
  •   richardtallent    16 年前

    我不熟悉这种HibernateTemplate语法,但您似乎在查询SQL中的原始字段名,而不是别名。试试这个:

    String query = "person.LastName = 'Johnson'"; 
    

    或者,也许:

    String query = "[person.LastName] = 'Johnson'"; 
    

    或者,可能:

    String query = "{person.LastName} = 'Johnson'"; 
    

    取决于在将最终SQL查询发送到服务器之前正在进行何种类型的预处理。

        3
  •  0
  •   Erich Kitzmueller    16 年前

    这是因为:value是查询中的绑定变量;不能简单地用包含任意字符串(将成为查询的一部分)的字符串替换它,只能用实际的 价值 . 在您的例子中,该值是“person.last_name='johnson'”,实际上是一个字符串,而不是布尔值。布尔值应该是 这两种方法对于您试图存档的内容都是相当无用的。

    绑定变量或多或少会替换文字,而不是复杂的表达式。