2009-05-12 15 views
1

Bei der Konvertierung über eine Legacy-Anwendung müssen wir die benannte Abfrage in nhibernate konvertieren. Das Problem ist, dass die Where-Klausel gesetzt wird.where-Klausel als Parameter

hier ist die Abbildung

<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> 

und C# -Code:

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

Der Fehler:

where ?]; ErrorCode []; An expression of non-boolean type specified in a context where a condition is expected, near '@p0'.

Antwort

2

Das funktioniert nicht, weil Sie versuchen, :value mit "person.LAST_NAME = 'Johnson'" ersetzen wollen, dass die Abfrage

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

wird. Sie können den "Johnson" -Teil nicht dynamisch ersetzen, nicht die ganze Bedingung. So wirklich bekommt, was erzeugt wird,

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

die offensichtlich keine gültige Bedingung für die WHERE-Teil ist, da es nur eine wörtliche, aber keine Spalte und Betreiber das Feld zu vergleichen.

Wenn Sie nur gegen person.LAST_NAME anzupassen haben zu umschreiben die XML-SQL-Abfrage

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

Und in der C# -Code gesetzt

String query = "Johnson"; 

Wenn Sie dynamisch von verschiedenen Spalten filtern müssen oder Auch mehrere Spalten gleichzeitig verwenden Filter. z.B.so (habe ich ein paar Annahmen über Sie Hibernate-Mapping-Datei)

<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> 

in Ihrem Code Jetzt sollten Sie in der Lage sein

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"); 

zu tun Wenn Sie noch mehr dynamische Abfragen (zB auch brauchen Veränderung der Operator (=,! =, like,>, <, ...) oder du musst die Einschränkungen logisch kombinieren (wo lastname = "foo" OR Vorname "=" foobar ") dann ist es definitiv Zeit in die zu schauen

Hibernate Criteria API

0

Ich bin nicht vertraut mit dieser HibernateTemplate Syntax, aber es sieht aus wie Sie fragen den ursprünglichen Feldnamen in SQL anstelle des Alias ​​ab. Versuchen Sie folgendes:

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

oder vielleicht:

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

oder möglicherweise:

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

Hängt was für die Vorverarbeitung vor sich geht, bevor die endgültige SQL-Abfrage gesendet wird der Server.

0

Das liegt daran: Wert ist eine Bindevariable in der Abfrage; Sie können es nicht einfach durch eine Zeichenfolge ersetzen, die eine beliebige Zeichenfolge enthält (die Teil der Abfrage werden würde), sondern nur mit einem tatsächlichen Wert. In Ihrem Fall ist der Wert "person.LAST_NAME = 'Johnson'", was eigentlich ein String ist, kein boolescher Wert. Boolesche Werte wären true oder false, die beide für das, was Sie versuchen zu archivieren, ziemlich nutzlos sind.

Bind-Variablen ersetzen mehr oder weniger Literale, keine komplexen Ausdrücke.