2012-09-12 13 views
5

Mit JPA arbeiten, ich möchte in der Lage sein, ein BitSet in der DB zu speichern und es natürlich zurück zu ziehen.Java BitSet in DB speichern

Angenommen, ich habe:

@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... 
} 

eine "Column" und sollte definieren? Ich verstehe nicht wirklich, wie es beibehalten wird (mit toString()?) Und darüber hinaus, wie es aus der DB geladen wird.

Können Sie mir bitte mit diesem helfen?

Danke!

Antwort

3

Standardmäßig verwendet JPA die Java-Serialisierung, um Eigenschaften unbekannter Typen Serializable persistent zu machen (so dass Sie eine serialisierte Darstellung als byte[] gespeichert haben).

Normalerweise ist es nicht das, was Sie wollen, weil es effizientere Möglichkeiten zur Darstellung Ihrer Daten geben kann. Beispielsweise kann BitSet effizient als Zahl dargestellt werden (wenn seine Größe beschränkt ist) oder byte[] oder etwas anderes (leider bietet BitSet keine Methoden für diese Konvertierungen, daher müssen Sie sie manuell implementieren).

Wenn Sie entschieden haben, welche Repräsentation der Daten Sie in der Datenbank haben möchten, müssen Sie JPA mitteilen, die notwendige Konvertierung anzuwenden. Es gibt zwei Optionen:

  • Implementierung in Getter und Setter implementieren. Zum Beispiel, wie folgt:

    @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 
        } 
        ... 
    } 
    
  • Verwenden anbieterspezifischen Erweiterung implizit die Umwandlung durchzuführen (beispielsweise in custom types Ruhezustand). Mit diesem Ansatz können Sie Ihre Typkonvertierungslogik in verschiedenen Entitäten wiederverwenden.

+0

Danke, das ist wie eine viel versprechende Antwort sieht :) – forhas

4

effizientere Art und Weise (das verwendet int statt byte[]) eine ziemlich einfache benutzerdefinierte Klasse erfordert:

@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); 
     } 
    } 
}