2009-05-12 10 views
1

レガシーアプリケーションでの変換では、名前付きクエリをnhibernateに変換する必要があります。問題は、where句が設定されていることです。ここ 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); 

エラー:

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

答えて

2

クエリこれは動作しません

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

なったことを望む"person.LAST_NAME = 'Johnson'":valueを交換しようとするので、これは動作しません。あなたは、条件全体ではなく動的に 'Johnson'部分を置き換えることができます。したがって、本当に生成されますすることにフィールドを比較するだけでなく、文字通りの無柱とオペレータがあると明らかにWHEREの部分のための有効な条件ではありません

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

です。

あなただけ

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

そして、C#コード内にXML-SQLクエリを書き直すperson.LAST_NAME照合する必要がある場合は、動的に別の列でフィルタリングする必要がある場合は

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

を行うことができるはず((私は、Hibernateマッピングファイルあなたにいくつかの仮定をしました) (例えば、lastname = "foo" OR firstname "=" foobar ")を論理的に結合する必要がある場合は、操作者(=、!=、like、>、<、...)

Hibernate Criteria API

0

私はこれのHibernateTemplateの構文に慣れていないんだけど、それがどのように見えますエイリアスではなくSQLで元のフィールド名を照会しています。

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

か、多分:

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

または、おそらく:

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

は、最終的なSQLクエリが送信される前に、前処理の並べ替えが何が起こっているかによって異なり、これを試してみてくださいサーバー。

0

これは、次の理由によるものです。valueはクエリのバインド変数です。実際のの値がの任意の文字列(クエリの一部になる)を含む文字列で置き換えることはできません。あなたの場合、値は "person.LAST_NAME = 'Johnson'"です。これは実際にはブール値ではなく文字列です。ブール値はまたはです。いずれもアーカイブしようとすると無駄になります。

バインド変数は、より複雑な表現ではなく、リテラルを置き換えます。

関連する問題