2012-09-12 29 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); 
     } 
    } 
}