引用来自其他实体的实体

时间:2014-12-12 21:14:58

标签: java entity-framework jpa java-ee-7

我的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
}

2 个答案:

答案 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设置关系的所有者,正如@ n​​eil-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错误。