7

与 JPA 合作,我希望能够将 BitSet 保存到数据库中并将其拉回。

假设我有:

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

我也应该定义一个“columnDefinition”吗?我真的不明白它是如何持久化的(使用 toString()?),而且它是如何从数据库中加载回来的。

你能帮我解决这个问题吗?

谢谢!

4

3 回答 3

5

更有效的方式(使用int代替byte[])需要一个非常简单的自定义类:

@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);
        }
    }
}
于 2014-03-18T11:50:14.550 回答
3

默认情况下,JPA 使用 Java 序列化来持久化未知Serializable类型的属性(以便您将序列化表示存储为byte[])。

通常这不是您想要的,因为可以有更有效的方法来表示您的数据。例如,BitSet可以有效地表示为一个数字(如果它的大小是有限的),或byte[],或其他东西(不幸的是,BitSet不提供进行这些转换的方法,因此您需要手动实现它们)。

当您决定要在数据库中使用哪种数据表示时,您需要告诉 JPA 应用必要的转换。有两种选择:

  • 在 getter 和 setter 中实现转换。例如,如下所示:

    @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
        }
        ...
    }
    
  • 使用特定于提供程序的扩展来隐式执行转换(例如, Hibernate 中的自定义类型)。这种方法允许您在不同的实体中重用您的类型转换逻辑。

于 2012-09-12T14:44:07.633 回答
0

您可以在 getter 方法中使用以下任何转换

byte[] bytes = bitSet.toByteArray();
long[] longs = bitSet.toLongArray();
于 2021-11-29T19:25:19.117 回答