2012-09-12 48 views
5

Al trabajar con JPA, me gustaría poder guardar un BitSet en el DB y recuperarlo, por supuesto.Guardar BitSet de Java en DB

Supongamos que tengo:

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

debe definir un "ColumnDefinition" también? Realmente no entiendo cómo persiste (usando toString()?) Y además, ¿cómo recupera la carga del DB?

¿Puedes ayudarme con esto?

Gracias!

Respuesta

3

De manera predeterminada, JPA usa la serialización de Java para conservar las propiedades de tipos desconocidos de Serializable (para que tenga una representación serializada almacenada como byte[]).

Por lo general, no es lo que quiere, porque puede haber maneras más eficientes de representar sus datos. Por ejemplo, BitSet se puede representar eficientemente como un número (si su tamaño está limitado) o byte[], o alguna otra cosa (desafortunadamente, BitSet no proporciona métodos para realizar estas conversiones, por lo tanto, debe implementarlas manualmente).

Cuando decidió qué representación de los datos desea tener en la base de datos, necesita decirle a JPA que aplique la conversión necesaria. Hay dos opciones:

  • Implementa la conversión en getters y setters. Por ejemplo, como sigue:

    @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 
        } 
        ... 
    } 
    
  • Uso extensión específica del proveedor para realizar la conversión implícita (por ejemplo, custom types en Hibernate). Este enfoque le permite reutilizar su lógica de conversión de tipo en diferentes entidades.

+0

Gracias, esto se ve como una respuesta prometedora :) – forhas

4

manera más eficiente (que utiliza int en lugar de byte[]) requiere un bastante simple clase personalizada:

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