2012-09-12 15 views
5

Lavorando con JPA, mi piacerebbe essere in grado di salvare un BitSet nel DB e ritirarlo.Salvataggio di BitSet java su DB

Supponiamo che io sono:

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

dovrebbe definire un "ColumnDefinition" come bene? Non capisco davvero come è persistito (usando toString()?) E inoltre come viene ripristinato dal DB.

Potete aiutarmi per favore con questo?

Grazie!

risposta

3

Per impostazione predefinita, JPA utilizza la serializzazione Java per mantenere le proprietà dei tipi sconosciuti Serializable (in modo da avere una rappresentazione serializzata memorizzata come byte[]).

Di solito non è quello che vuoi, perché ci possono essere modi più efficienti per rappresentare i tuoi dati. Ad esempio, BitSet può essere rappresentato in modo efficiente come un numero (se la sua dimensione è limitata) o byte[] o qualcos'altro (sfortunatamente, BitSet non fornisce metodi per eseguire queste conversioni, quindi è necessario implementarle manualmente).

Quando hai deciso quale rappresentazione dei dati vuoi avere nel database devi dire a JPA di applicare la conversione necessaria. Ci sono due opzioni:

  • Implementare la conversione in getter e setter. Ad esempio, come segue:

    @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 
        } 
        ... 
    } 
    
  • Usa specifico del provider estensione per eseguire la conversione in modo implicito (ad esempio, custom types in Hibernate). Questo approccio consente di riutilizzare la logica di conversione del tipo in diverse entità.

+0

Grazie, questo appare come una risposta promettente :) – forhas

4

modo più efficiente (che utilizza int invece di byte[]) richiede una piuttosto semplice classe personalizzata:

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