Hibernate通用字段

时间:2017-01-13 04:04:05

标签: java hibernate generics jpa spring-data

我正在尝试在以下数据库表的Hibernate中创建映射类:

CREATE TABLE values (
    id SMALLINT,
    name NVARCHAR(50) NOT NULL,
    type NVARCHAR(10) NOT NULL,
    text NVARCHAR(MAX) NULL,
    numeric NUMERIC NULL,
    boolean BIT NULL,
    date DATETIME NULL,
    CONSTRAINT c1 CHECK(type IN ('TEXT','NUMERIC','BOOLEAN','DATE'))
);

目前我有以下实现,但我不想重新定义每个子类中的每个属性,因为它不使用父代的通用实现:

@Entity
@Table(name = "values")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
public abstract class Value<T extends Serializable> {
    @Id
    private int id;
    private String name;
    @Transient
    private T value;

    public T getValue() {
        return value;
    }
    public void setValue(T value) {
        this.value = value;
    }
}

值类型

@Entity
@DiscriminatorValue("TEXT")
public class TextValue extends Value<String> {
    private String text;

    @Override
    public String getValue() {
        return text;
    }
}
@Entity
@DiscriminatorValue("NUMERIC")
public class NumericValue extends Value<Double> {
    private Double numeric;

    @Override
    public Double getValue() {
        return numeric;
    }
}
@Entity
@DiscriminatorValue("BOOLEAN")
public class BooleanValue extends Value<Boolean> {
    private Boolean boolean;

    @Override
    public Boolean getValue() {
        return boolean;
    }
}
@Entity
@DiscriminatorValue("DATE")
public class DateValue extends Value<LocalDateTime> {
    private LocalDateTime date;

    @Override
    public LocalDateTime getValue() {
        return date;
    }
}

我尝试使用@AttributeOverride来更改每个子类中的列名,但它没有效果。

如果有另一种方法可以实现上表中的键值结构,并且可以使用Java中的泛型进行映射也很有价值。

1 个答案:

答案 0 :(得分:0)

尝试使用不同的映射,而不是@Transient值:

@Entity
@Table(name = "values")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
public abstract class Value<T extends Serializable> 
{
    @Id
    protected int id;

    protected String name;


    public abstract T getValue();

    public abstract void setValue(T value);
}

@Entity
@DiscriminatorValue("TEXT")
public class TextValue extends Value<String> 
{
    @Column(name = "text")
    private String value;

    @Override
    public String getValue() 
    {
        return value;
    }

    @Override
    public void setValue(String value) 
    {
        this.value = value;
    }
}

@Entity
@DiscriminatorValue("NUMERIC")
public class NumericValue extends Value<Double> 
{
    @Column(name = "numeric")
    private Double value;

    @Override
    public Double getValue() 
    {
        return value;
    }

    @Override
    public void setValue(Double value) 
    {
        this.value = value;
    }
}

等等

嗯,好处非常有限,因为我觉得你可能想要这样的东西:

@Entity
public class Something
{
    ...

    @OneToMany(cascade = ALL, orphanRemoval = true)
    @JoinColumn(name = "SOMETHING_ID")
    private Set<Value<?>> values = new LinkedHashSet<>();

    ...
}

在这种情况下,唯一的好处是内部值由ORM转换为正确的类,因此这不是您的责任。

尽管如此,您必须(并且无法避免,与任何其他模型一起使用)使用繁琐的instanceof污染您的业务逻辑/表示控制器。