2016-04-25 6 views
0

私が作業しているレガシーコードでは、UserType属性を含むHibernateモデルがあります。さらに、Oracle最適化では「false」がnullとして格納されます。UserTypeカラムを使用しているHibernateのクエリは、nullSafeSetを使用して変換を行いません。

/** 
* Data type for a boolean value stored in a NUMBER oracle column. 1 evaluates 
* to true, null evaluates to false. 
* 
* This is designed for oracle indexing, since null values are not indexed. 
* 
* 
*/ 

public class BooleanUserType implements UserType { 
    private static final int[] SQL_TYPES = { Types.INTEGER }; 

    public int[] sqlTypes() { 
     return SQL_TYPES; 
    } 

    public Class<?> returnedClass() { 
     return Boolean.class; 
    } 

    public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException { 
     Boolean result = false; 
     resultSet.getInt(names[0]); 
     if (!resultSet.wasNull()) { 
      result = true; 
     } 
     return result; 
    } 

    public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException { 
     Boolean input = (Boolean) value; 
     if (input == null || input == false) { 
      preparedStatement.setNull(index, Types.INTEGER); 

     } else { 
      preparedStatement.setInt(index, 1); 
     } 
    } 

    public Object deepCopy(Object value) throws HibernateException { 
     return value; 
    } 

    public boolean isMutable() { 
     return false; 
    } 

    public Object assemble(Serializable cached, Object owner) throws HibernateException { 
     return cached; 
    } 

    public Serializable disassemble(Object value) throws HibernateException { 
     return (Serializable) value; 
    } 

    public Object replace(Object original, Object target, Object owner) throws HibernateException { 
     return original; 
    } 

    public int hashCode(Object x) throws HibernateException { 
     return x.hashCode(); 
    } 

    public boolean equals(Object x, Object y) throws HibernateException { 
     if (x == y) 
      return true; 
     if (null == x || null == y) 
      return false; 
     return x.equals(y); 
    } 

このBooleanUserTypeは、このためのカラム(編集)モデルとして使用される:エンティティが を更新/保存されているときnullSafeSetの両方呼び出されthis StackOverflow reply

によれば

public class CustomString implements Serializable{ 
    private static final long serialVersionUID = -5311205585865001342L; 

    @Id 
    @Column(name="custom_string_id") 
    private Long id; 

    @Column(name="text") 
    private String text; 

    @Column(name="active") 
    @Type(type="my.org.BooleanUserType") // store false as 'null' -- an Oracle optimization 
    private Boolean active; 

    (...) 

クエリパラメータを設定する必要がある場合

ただし、これは私がこのモデルのためにブール値activeの列を使用してクエリを実行すると変換が行われず、予期した結果が得られないため、私が観察している動作ではありません。

私はDBに保存されてCustomStringオブジェクトを持っている:

new CustomString(1, "text", Boolean.FALSE); 

私は私が期待するように動作していないクエリを作る:私が代わりにこれを行う

Criteria c = session.createCriteria(CustomString.class); 
c.add(Restrictions.eq("active", Boolean.FALSE)); 
c.list() // No results! 

場合、それは動作します:

Criteria c = session.createCriteria(CustomString.class); 
c.add(Restrictions.isNull("active")); 
c.list() // Expected result! 

またの代わりにBoolean.TRUEでオブジェクトを保存3210を入力し、TRUEを照会すると正常に動作します。

nullSafeSetメソッドにデバッグログの行がいくつか追加されていて、クエリの作成時に呼び出されないことを確認できます。

nullSafeSet実際にHibernateによって呼び出され、何らかの形で期待通りに動作しない場合、または私には何かがありません。別の方法でこれにアプローチする必要がありますか?

答えて

0

ロジックは、挿入/更新シナリオでオブジェクトを実際にフラッシングするときにのみ評価されます。 Criteraクエリを構築するとき、Hibernateは@Columnアノテーションを使用してカラム名を決定しますが、自動的に "= FALSE"を "is null"に置き換えません。

Hibernateは常に実行されるように、より正確には、クエリのSELECT部分は、あなたのクラスで定義され@Columnsによりごとに決定される:

SELECT custom_string_id, text, active FROM [schema].[table_name] 

をごCriteriaRestrictionsの追加がWHERE述語を強化しますが、エンティティのインスタンスに解析される行が戻されるまで、ロジックを利用することはありません(BooleanUserType)。

最後に、私はあなたが言及されたOracleの最適化わからないんだけど、あなたはNULL値がインデックスから脱落するという事実を活用しようとしているならば、あなたはNULL代わりのFalseなどを照会したくないかもしれませんフル・テーブル・スキャンを実行します。しかし、アクティブな行(True)だけを気にしていて、非アクティブな行を効果的に廃止/アーカイブしたい場合は、古いデータをNULLに設定する方法では、実際に参照しているインデックスのパフォーマンスが向上します。

+0

代わりにカスタムタイプを使用するのはどうですか? http://learningviacode.blogspot.ie/2011/09/creating-hibernate-custom-type-2.html – mendez8

+0

私はそれについて大きな期待はしていませんが、これをチェックしてみてください。http:// stackoverflow .com/questions/29145693/custom-like-predicate-to-handle-custom-user-defined-types-hibernate-usertype –

関連する問題