改进现有数据库模式的JPA实体类

时间:2013-11-21 22:02:58

标签: java hibernate jpa enums

我正在尝试在现有架构上实现Hibernate / JPA2解决方案,该解决方案无法更改。以下是现有架构的最小示例:

CREATE TABLE REASON (
  REASON_CODE CHAR(1),
  REASON_DESCRIPTION CHAR(50))

CREATE TABLE HEADER (  
  REASON_CODE CHAR(1),
  OTHERFIELD1 CHAR(40),
  OTHERFIELD2 CHAR(40) )

通常,这将是从DB角度看的“正确”方式:REASON_CODE将REASON链接到HEADER。然而,它给我带来了Java中一个尴尬的问题,我不确定解决它的最佳方法。我已将这些实体建模如下:

@Entity
@Table(name="REASON")
public class Reason  implements java.io.Serializable {
    @Id
    @Column(name="REASON_CODE", unique=true, nullable=false, length=1)
    private Character reasonCode;
    @Column(name="REASON_DESCRIPTION", nullable=false, length=25)
    private String reasonDescription;
}


@Entity
@Table(name="HEADER")
public class Header implements java.io.Serializable {
    @ManyToOne
    @JoinColumn(name = "REASON_CODE", nullable = false)
    private Reason reason;
    @Column(name="OTHERFIELD1")
    private String otherField1;
    @Column(name="OTHERFIELD2")
    private String otherField2;
}

据我所知,从Java的角度来看,这是“正确的” - 将Header与Reason链接在一起。

问题在于,当我需要在我的代码中使用其中一个Reason值时,我会遇到一些尴尬的语法:

Reason r = reasonService.findOne('X'); //  X is the REASON_CODE in the database record
// Do some processing with variable r

或者这个:

header.setReason(reasonService.findOne('X'));   

理想情况下,我可以将Reason实现为枚举,如:

public enum Reason {
    X_MARKSTHESPOT("X"),
    C_MEANSSOMETHINGELSE("C"),
    F_MEANSATHIRDTHING("F") ;

    private String code;

    private Reason(String code) {
        this.code = code;
    }
}

然后在我的代码中简单地说明这一点:

header.setReason(Reason.X_MARKSTHESPOT);    

但是从understand开始,JPA是不可能的,它只提供EnumType.STRING(基本上是名称)或EnumType.ORDINAL(更糟糕的是,枚举列表中的索引)。一个可能的方法是JPA 2.1的Converter,但我从未使用它。我还阅读了here(在其中一个答案中)Hibernate User Type可能有用。我们的程序员之一通过编写两个完整的类来解决这个问题 - 一个用于内部使用的枚举类和一个“影子”类,它遍历枚举并在每次启动时同步数据库中的记录。但这似乎是一种执行它的方式。 处理此问题的最佳方法是什么,请记住无法更改数据库架构?

0 个答案:

没有答案