我有 2 个表,第一个是可变的,第二个只包含常量:
USER.ID USER.NAME USER.USER_TYPE (FK on USER_TYPE.ID)
INT VARCHAR(64) INT(1)
----------------------------------
1 Alex 3
2 Jane 1
3 Carl 3
USER_TYPE.ID USER_TYPE.VALUE
INT(1) VARCHAR(64)
------------------------------
1 PENDING
2 REGISTERED
3 BANNED
4 ACTIVE
外键USER.USER_TYPE
是必需的,并引用表USER_TYPE
中的主键USER_TYPE.ID
(一对一关系(。这是我在Hibernate中的映射。
用户.java
@Entity
@Table(name = "USER")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "NAME")
private String name;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "USER_TYPE")
private UserType userType;
}
用户类型.java
@Entity
@Table(name = "USER_TYPE")
public class UserType {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "VALUE")
private String value;
}
我的目标是将枚举的值保留在数据库中。如何将UserType
的值而不是 id 映射到User
和验证它?我想将常量 VALUE 传递给字符串而不是它的 ID。
private String userType;
第一个用户的预期结果将是:
User[id=1, name=Alex, userType=Banned]
User[id=2, name=Jane, userType=Pending]
User[id=3, name=Carl, userType=Banned]
我的尝试是在两个列切换的情况下两次在表格定义上使用此注释
@SecondaryTable(name="USER_TYPE",
pkJoinColumns={@PrimaryKeyJoinColumn(name="ID", referencedColumnName="USER_TYPE")}
)
并通过以下方式获取值
@Column(table="USER_TYPE", name="VALUE")
private String UserType;
但是它会导致错误
找不到具有逻辑名称的列:在 org.hibernate.mapping.Table(USER( 及其相关的超级表和辅助表中USER_TYPE
首先,您需要将关系从@OneToOne
更改为@ManyToOneUserType
因为一个或多个User
可以使用User
并且可以有一个UserType
。
其次使用引用的列名称,它引用:
此外键列引用的列的名称。
因此User
实体将是:
@Entity
@Table(name = "USER")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "NAME")
private String name;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "USER_TYPE", referencedColumnName = "VALUE")
private UserType userType;
}
在UserType
中,您应该使用 @NaturalId 对字段 + 不提供其资源库应用唯一约束value
以防止重复值,因为它可能导致不一致:
@Entity
@Table(name = "USER_TYPE")
public class UserType {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@NaturalId
@Column(name = "VALUE")
private String value;
}
希望它能解决问题!
枚举可以更简单:
enum UserType {
PENDING,
REGISTERED,
BANNED,
ACTIVE
}
@Entity
@Table(name = "USER")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "NAME")
private String name;
@javax.persistence.Enumerated
private UserType userType;
}
如果你真的需要单独的表和@OneToOne关系,你可以使用 Hibernate 中的@Formula:
@Formula("(select ut.value from user_type ut where ut.ID = USER_TYPE)")
private String userType;
对于这个非常特殊的要求,你可以使用辅助表注释。 也就是说,您不需要 UserType 实体,而是在用户实体中将属性 userType 声明为字符串,并将列映射到辅助表"USER_TYPE"。
首先,我建议你使用ManyToOne
关系。 和 不CascadeType.ALL
如果您不计划更新或删除表USER_TYPE
。
如果您不需要添加新UserTypes
请经常使用枚举。它会随心所欲地工作。
第二种解决方案:只要fetch = FetchType.EAGER
就可以在getter中添加瞬态字段并返回UserType
值。