2012-09-12 25 views
5

Praca z JPA, chciałbym móc zapisać BitSet do DB i wycofać go z powrotem.Zapisywanie java BitSet na DB

Załóżmy, że mam:

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

powinna określić "columnDefinition", jak również? Naprawdę nie rozumiem, w jaki sposób jest utrzymywany (przy użyciu toString()?), A ponadto, w jaki sposób pobiera z powrotem z DB.

Czy możesz mi pomóc z tym?

Dzięki!

Odpowiedz

3

Domyślnie JPA korzysta z serializacji Java w celu zachowania właściwości nieznanych typów Serializable (tak, że istnieje szeregowana reprezentacja zapisana jako byte[]).

Zazwyczaj nie jest to, czego potrzebujesz, ponieważ mogą istnieć skuteczniejsze sposoby przedstawiania danych. Na przykład: BitSet może być skutecznie reprezentowany jako liczba (jeśli jego rozmiar jest ograniczony), lub byte[], lub coś innego (niestety, BitSet nie zapewnia metod wykonywania tych konwersji, dlatego trzeba je wdrożyć ręcznie).

Kiedy zdecydowałeś, jaką reprezentację danych chcesz mieć w bazie danych, musisz powiedzieć WZP, aby zastosować odpowiednią konwersję. Dostępne są dwie opcje:

  • Implementacja konwersji w programach pobierających i ustawiających. Na przykład, w następujący sposób:

    @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 
        } 
        ... 
    } 
    
  • Korzystanie rozszerzenie dostawca specyficzne wykonać konwersję niejawnie (np custom types w Hibernate). Takie podejście pozwala na ponowne użycie logiki konwersji typu w różnych jednostkach.

+0

Dziękuję, to wygląda obiecująco odpowiedź :) – forhas

4

bardziej efektywny sposób (który używa int zamiast byte[]) wymaga dość prosty niestandardową klasę:

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