2012-09-12 99 views
5

使用JPA,我希望能夠將一個BitSet保存到數據庫並將其拉回。將java位設置保存爲DB

假設我有:

@Entity 
@Table(name = "myTable") 
public class MyClass { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "Object_Id") 
    protected long id; 

    @Column(name = "Tags") 
    protected BitSet tags; 

... getters & setters etc... 
} 

應該定義一個 「columnDefinition」 呢?我真的不明白它是如何保持的(使用toString()?),而且它是如何從數據庫中獲取負載的。

你能幫我這個嗎?

謝謝!

回答

3

默認情況下,JPA使用Java序列化來保存未知的Serializable類型的屬性(以便您將序列化表示存儲爲byte[])。

通常這不是你想要的,因爲可以有更有效的方式來表示你的數據。例如,BitSet可以高效地表示爲數字(如果其大小有界)或byte[]或其他(不幸的是,BitSet未提供執行這些轉換的方法,因此您需要手動實現它們)。

當您決定要在數據庫中包含哪些數據表示時,您需要告知JPA應用必要的轉換。有兩種選擇:

  • 在獲取者和設置者中實現轉換。例如,如下所示:

    @Entity 
    @Table(name = "myTable") 
    @Access(AccessType.FIELD) 
    public class MyClass { 
        ... 
        @Transient // Do not store this field 
        protected BitSet tags; 
    
        @Access(AccessType.PROPERTY) // Store the property instead 
        @Column(name = "Tags") 
        byte[] getTagsInDbRepresentation() { 
         ... // Do conversion 
        } 
    
        void setTagsInDbRepresentation(byte[] data) { 
         ... // Do conversion 
        } 
        ... 
    } 
    
  • 使用提供者特有的擴展(在休眠例如,custom types)隱式地執行轉換。這種方法允許您在不同實體中重用您的類型轉換邏輯。

+0

謝謝,這看起來像一個有前途的答案:) – forhas

4

更有效的方式(即使用int,而不是byte[])需要一個非常簡單的自定義類:

@Entity 
@Access(AccessType.FIELD) 
public class SampleEntity { 

    @Transient 
    private IntBitSet isolationLevel = new IntBitSet(0); 

    public static final int USER_BIT = 0; 
    public static final int DEVICE_BIT = 1; 
    // 2, 3, 4, ... 

    public boolean isUserIsolated() { 
     return isolationLevel.bitGet(USER_BIT); 
    } 

    public boolean isDeviceIsolated() { 
     return isolationLevel.bitGet(DEVICE_BIT); 
    } 

    public void setUserIsolated(boolean b) { 
     isolationLevel.bitSet(USER_BIT, b); 
    } 

    public void setDeviceIsolated(boolean b) { 
     isolationLevel.bitSet(DEVICE_BIT, b); 
    } 

    @Access(AccessType.PROPERTY) 
    @Column 
    public int getIsolationLevel() { 
     return isolationLevel.getValue(); 
    } 

    public void setIsolationLevel(int isolationLevel) { 
     this.isolationLevel = new IntBitSet(isolationLevel); 
    } 

    private static class IntBitSet { 
     private int value; 

     public IntBitSet(int value) { 
      this.value = value; 
     } 

     public int getValue() { 
      return value; 
     } 

     public boolean bitGet(int i) { 
      return ((value >> i) & 1) == 1; 
     } 

     public void bitSet(int i, boolean b) { 
      if (b) { 
       bitSet(i); 
      } else { 
       bitUnset(i); 
      } 
     } 
     private void bitSet(int i) { 
      value = value | (1 << i); 
     } 
     private void bitUnset(int i) { 
      value = value & ~(1 << i); 
     } 
    } 
}