我正在尝试做一些看似简单但我无法弄清楚的事情。我正在使用 JPA2 和休眠,但我想要一个也可以与 EclipseLink 等其他提供商一起使用的解决方案,但这是次要问题。
我有一个凭证表,其中只有一个密码哈希、一个盐和一个用户 ID。我有一个包含一些用户数据的用户表。
以下是我的要求:
- 每个用户都必须拥有一个凭证,因此它是一对一的。
- 该应用程序只需要创建用户和登录的凭据
- 许多其他对象包含用户(即发票、历史记录、地址等),我不希望这些对象在我每次对其进行操作时都间接加载凭据。
- 我希望在清理用户时自动清理凭据。
所以这是我的第一次尝试:
@Entity
public class Credential {
@Id
private Long id;
@MapsId
@OneToOne( optional = false ) // Btw, I don't care if this is lazy loaded or not
@JoinColumn( name = "user_id" )
private User user;
...
public Credential( User user, String password ) {
this.user = user;
// set salt and hash from password
}
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
@OneToOne( optional=false, mappedBy="user", cascade = CascadeType.ALL, fetch = FetchType.LAZY )
private Credential credential; // this I do what lazy loaded
...
public void setPassword( String password ) {
credential = new Credential( this, password );
}
User user = new User();
user.setName( "Charles Bukowski" );
user.setPassword( "b00z3" );
service.transactedPersist( user );
对此。
好的,所以现在当我坚持用户时,你能猜到会发生什么吗?对,我在插入凭据时遇到数据完整性异常。那是因为,是的,user.id 设置正确,但用户表中还没有行。如果我使凭据 optional=true 它神秘地起作用,但是在持久化之后我似乎在 User 上获得了额外的更新,并且我引用用户的所有查询现在也查询凭据。
老实说,如果我不需要级联删除,我什至不会在用户中引用凭据。如果我在没有 JPA 的情况下这样做,我会这样做。每次删除用户时,我都会设置要删除的凭据,但在用户凭据中没有引用。但是使用 JPA,我只能确保在 User.xml 中添加一个属性时清除 Credential。
无论如何,要求是重要的部分,所以如果你认为我应该使用不同的设计来实现这一点,我完全愿意接受更好的设计。:)
老实说,我希望 JPA 能够使用“引用”作为字段。我的大多数使用 User 的对象实际上只需要他的唯一 ID。但我似乎每次阅读引用实体时都会加载他和凭据(以及用户中的其他 OneToOne 映射)。
提前致谢,
哦,我认为其中一些问题的答案可能是使用带有延迟加载的字节码检测。但我正在使用带有 CTW 和 Intellij 的 Spring。所以当我在 IntelliJ 中调试集成测试时,我真的不知道如何实现这一点。所以那里的任何指示都会很棒。