在转换遗留应用程序时,我们需要将命名查询转换为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);
错误:
在哪里?];错误代码 [];在预期条件的上下文中指定的非布尔类型的表达式,位于“@ p0”附近。
答案 0 :(得分:2)
这不起作用,因为您尝试将: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-query重写为
<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-mapping文件做了一些假设)
<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");
如果您还需要更多动态查询(例如,甚至更改运算符(=,!=,like,&gt;,&lt;,...),或者您必须在逻辑上组合限制(其中lastname =“foo”或者名字“=”foobar“)那么明确的时间来看看
答案 1 :(得分:0)
我不熟悉这个HibernateTemplate语法,但看起来你在查询SQL中的原始字段名而不是别名。试试这个:
String query = "person.LastName = 'Johnson'";
或者,也许:
String query = "[person.LastName] = 'Johnson'";
或者,可能:
String query = "{person.LastName} = 'Johnson'";
取决于在将最终SQL查询发送到服务器之前进行何种预处理。
答案 2 :(得分:0)
那是因为:value是查询中的绑定变量;你不能简单地用包含任意字符串的字符串(它将成为查询的一部分)替换它,只能使用实际的值。在您的情况下,值为“person.LAST_NAME ='Johnson'”,它实际上是一个字符串,而不是布尔值。布尔值将是 true 或 false ,这两者对于您尝试存档的内容都是无用的。
绑定变量或多或少取代文字,而不是复杂的表达。