我正在尝试在现有架构上实现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可能有用。我们的程序员之一通过编写两个完整的类来解决这个问题 - 一个用于内部使用的枚举类和一个“影子”类,它遍历枚举并在每次启动时同步数据库中的记录。但这似乎是一种执行它的方式。 处理此问题的最佳方法是什么,请记住无法更改数据库架构?