2012-09-12 22 views
5

Làm việc với JPA, tôi muốn có thể lưu một BitSet vào DB và kéo nó trở lại ofcourse.Lưu java BitSet vào DB

Giả sử tôi có:

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

nên xác định một "ColumnDefinition" không? Tôi không thực sự hiểu làm thế nào là nó tồn tại (bằng cách sử dụng toString()?) Và hơn nữa làm thế nào nó được tải trở lại từ DB.

Bạn có thể giúp tôi với điều này không?

Cảm ơn!

Trả lời

3

Theo mặc định JPA sử dụng tuần tự hóa Java để lưu giữ các thuộc tính không xác định của các loại Serializable không xác định (để bạn có một đại diện được lưu trữ được lưu trữ dưới dạng byte[]).

Thông thường, đó không phải là những gì bạn muốn, bởi vì có thể có những cách hiệu quả hơn để thể hiện dữ liệu của bạn. Ví dụ: BitSet có thể được biểu diễn một cách hiệu quả dưới dạng số (nếu kích thước của nó bị chặn) hoặc byte[] hoặc thứ khác (không may, BitSet không cung cấp các phương pháp để thực hiện các chuyển đổi này, do đó bạn cần triển khai chúng theo cách thủ công).

Khi bạn quyết định việc biểu diễn dữ liệu nào bạn muốn có trong cơ sở dữ liệu, bạn cần nói với JPA áp dụng chuyển đổi cần thiết. Có hai tùy chọn:

  • Thực hiện chuyển đổi trong getters và setters. Ví dụ, như sau:

    @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 
        } 
        ... 
    } 
    
  • Sử dụng phần mở rộng cung cấp dịch vụ cụ thể để thực hiện việc chuyển đổi ngầm (ví dụ, custom types trong Hibernate). Cách tiếp cận này cho phép bạn sử dụng lại logic chuyển đổi loại của bạn trong các thực thể khác nhau.

+0

Cảm ơn bạn, điều này có vẻ như một câu trả lời đầy hứa hẹn :) – forhas

4

cách hiệu quả hơn (có sử dụng int thay vì byte[]) đòi hỏi một lớp tùy chỉnh khá đơn giản:

@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); 
     } 
    } 
} 
Các vấn đề liên quan