где предложение в качестве параметра - PullRequest
1 голос
/ 12 мая 2009

В случае преобразования через устаревшее приложение нам нужно преобразовать именованный запрос в 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 '.

Ответы [ 3 ]

2 голосов
/ 26 июня 2009

Это не работает, потому что вы пытаетесь заменить :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'

Это не сработает. Вы можете динамически заменять только часть Джонсона, а не все условие. Таким образом, что действительно генерируется, это

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>
  ...
  <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" <strong>ИЛИ firstname "=" foobar ") тогда самое время заглянуть в

API Критерий гибернации

0 голосов
/ 26 июня 2009

Это потому, что: значение является переменной связывания в запросе; Вы не можете просто заменить ее строкой, которая содержит произвольную строку (которая станет частью запроса), только с фактическим значением . В вашем случае это значение person.LAST_NAME = 'Johnson', которое на самом деле является строкой, а не логическим значением. Логические значения будут true или false , оба из которых довольно бесполезны для того, что вы пытаетесь архивировать.

Привязка переменных более или менее заменяет литералы, а не сложные выражения.

0 голосов
/ 13 мая 2009

Мне не знаком этот синтаксис HibernateTemplate, но похоже, что вы запрашиваете исходное имя поля в SQL, а не псевдоним. Попробуйте это:

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

или, может быть:

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

или, возможно:

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

Зависит от того, какая предварительная обработка выполняется перед отправкой окончательного запроса SQL на сервер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...