我正在尝试做一些看似简单但我无法弄清楚的事情。我正在使用JPA2和hibernate,但我想要一个也可以与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设置正确,但用户表中还没有行。如果我使凭证可选=真,它神秘地起作用,但我似乎在持久化后获得用户的额外更新,我现在引用用户的所有查询也查询凭证。
说实话,如果我不需要级联删除,我甚至不会在用户中引用凭据。如果我在没有JPA的情况下这样做,我就会这样做。我会在每次删除用户时设置要删除的凭据,但在User for Credential中没有引用。但是使用JPA,如果我在User中添加了一个属性,我只能确保清除Credential。
无论如何,要求是重要的部分,所以如果你认为我应该使用不同的设计来实现这一目标,我会完全接受一个更好的设计。 :)
老实说,我希望JPA能够使用“引用”作为字段。我使用User的大多数对象实际上只需要他唯一的id。但是每当我读取推荐实体时,我似乎都会加载他和凭证(以及用户中的其他OneToOne映射)。
提前致谢,
哦,我认为其中一些问题的答案可能是使用延迟加载的字节码检测。但是我使用Spring和CTW以及Intellij。因此,当我在IntelliJ中调试集成测试时,我无法弄清楚如何实现这一点。所以任何指针都会很棒。