2016-04-25 23 views
0

在我正在使用的一些遺留代碼中,我有一個包含UserType屬性的Hibernate模型來表示使用整數進行索引的布爾值。另外,它爲ORACLE優化存儲'false'爲空。在Hibernate中使用UserType列進行查詢不會使用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被用作該(編)模型柱:

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; 

    (...) 

根據this StackOverflow reply

nullSafeSet被調用都被保存在實體時的/更新的 當查詢參數需要設置時

但是,這不是我正在觀察的行爲,因爲當我使用active列的布爾值查詢此模型時,未進行轉換,並且我沒有得到預期的結果。

我保存在一個數據庫中的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代替FALSE,然後查詢TRUE,工作正常。

我在我的nullSafeSet方法中添加了一些調試日誌行,並且我可以驗證它在進行查詢時未被調用。

應該由Hibernate實際調用nullSafeSet,並且不知如何按預期工作,或者我缺少某些東西,我應該以不同的方式處理這個問題?

回答

0

只有在插入/更新場景中實際將對象清理到數據庫時,纔會評估邏輯底層邏輯nullSafeSet()。在建立Critera查詢時,休眠將使用@Column註釋來確定列名稱,但不會自動將「= FALSE」翻轉爲「is null」。

更準確地說,查詢的SELECT部分是通過在類中定義的@Columns每個決定,所以Hibernate會始終運行:

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

添加RestrictionsCriteria將增加有WHERE謂語,但它不會利用你的邏輯,直到它將行解析成實體的實例。

最後,我不確定你指的是哪個Oracle優化,但是如果你試圖利用空值從索引中退出的事實,那麼你可能不想查詢NULL而不是False作爲它會運行全表掃描。但是,如果您只關心活動(True)行,並且您希望有效棄用/存檔非活動行,那麼將舊數據設置爲NULL的方法確實會爲您帶來指向您的索引性能增益。

+0

如何使用自定義類型呢? http://learningviacode.blogspot.ie/2011/09/creating-hibernate-custom-type-2.html – mendez8

+0

我沒有太高的期望,但你可能想檢查一下:http:// stackoverflow .COM /問題/ 29145693 /樣定製謂到手柄定製用戶定義類型,休眠,用戶類型 –

相關問題