我的Java EAR中有两个实体:用户和密码。当然,这些表在数据库中有相应的表:用户和密码。密码表包含用户的id作为外键。所以我的问题是,当使用纯注释从Users表创建用户时,如何从密码表中提取密码条目?我不知所措。
我不想使用业务逻辑来访问用户的相关密码实体 - 所以我需要容器为我这样做。
SCCE:
@Entity
@Table(name = "USERS")
public class User{
@Id
@Basic(optional = false)
@NotNull
@Column(name = "IDENTIFIER", nullable = false)
private Long identifier;
@JoinColumn(name = "UserIdentifier")
@OneToOne
private Password password;
// getters, setters, and other User related information such as username
}
@Entity
@Table(name = "PASSWORDS")
public class Password{
@Id
@Basic(optional = false)
@NotNull
@Column(name = "IDENTIFIER", nullable = false)
private Long identifier;
@JoinColumn(name = "USERIDENTIFIER", referencedColumnName = "IDENTIFIER", nullable = false)
@OneToOne(optional = false, fetch = FetchType.EAGER)
private User useridentifier;
//getters, setters, and other password related fields such as the password it's self
}
答案 0 :(得分:0)
实体类只是建立数据和关系。您从业务逻辑中的特定实例检索数据。您已在User和Password属性上与@OneToOne注释建立了关系。您缺少的是密码实体的持久字段。
@Entity
@Table(name = "PASSWORDS")
public class Password{
@Id
@Basic(optional = false)
@NotNull
@Column(name = "IDENTIFIER", nullable = false)
private Long identifier;
@JoinColumn(name = "USERIDENTIFIER", referencedColumnName = "IDENTIFIER", nullable = false)
@OneToOne(mappedBy = "password", optional = false, fetch = FetchType.EAGER)
private User useridentifier;
@NotNull
private String passwordValue;
// getters/setters go here, since your annotated fields are private
}
然后,您可以通过检索用户实例并导航到关系字段来遍历关系。因此,您的业务逻辑可能如下所示:
@PersistenceContext
EntityManager em;
Long userIdInput = ...;
String passwordInput = ...;
User user = em.find(User.class, userIdInput);
// compare the input password with the stored password
// retrieve the Password instance by navigating to the relationship field
if (passwordInput.equals(user.getPassword().getPasswordValue()) {
// passwords match
} else {
// passwords don't match
}
你的用户名为Long值,这是......奇怪的。您应该研究如何安全地处理在数据库中存储密码值的处理,因为将它们保存为未加密并不是一个好的做法。但这是JPA的要点。
编辑:需要使用mappedBy设置关系的所有者,正如@ neil-stockton所指出的那样。
答案 1 :(得分:0)
原来答案很简单。我有正确的注释,但我需要一些额外的东西。以下是两个实体的相关代码。
@Entity
@Table(name = "USERS")
public class User{
@Id
@Basic(optional = false)
@NotNull
@Column(name = "IDENTIFIER", nullable = false)
private Long identifier;
@JoinColumn(referencedColumnName = "PASSWORDS.USERIDENTIFIER", name="USERS.IDENTIFIER")
@OneToOne
private Password password;
// getters, setters, and other User related information such as username
}
@Entity
@Table(name = "PASSWORDS")
public class Password{
@Id
@Basic(optional = false)
@NotNull
@Column(name = "IDENTIFIER", nullable = false)
private Long identifier;
@JoinColumn(name = "USERIDENTIFIER", referencedColumnName = "IDENTIFIER", nullable = false)
@OneToOne(optional = false, fetch = FetchType.EAGER)
private User useridentifier;
//getters, setters, and other password related fields such as the password it's self
}
因此,对于拥有一个引用另一个实体的实体的未来堆栈器,您应该指定JoinColumn批注的名称和referencedColumnName,以使容器能够引入相关实体。通过执行此操作,我能够从数据库中提取正确的密码行。请注意,用户实体中的joincolumn批注也必须具有表名,并且密码实体中的相同批注必须不具有表名。它不会起作用 - 相信我,我试了一下并得到了StackOverflow错误。