JPA 对一对一关系执行级联操作



我对一对一的关系有以下问题(我猜也是一对一(:

假设我有下表:

create table user (
id bigint auto_increment primary key,
username varchar(100) not null,
constraint UK_username unique (username)
);
create table user_details(
userId bigint not null primary key,
firstName varchar(100) null,
lastName  varchar(100) null,
constraint user_details_user_id_fk foreign key (userId) references user (id)
);

如您所见,这两个表共享相同的主键。现在我创建的实体如下:

import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
@Data
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Column(unique = true)
@Size(min = 1, max = 100)
private String username;
@MapsId
//without this I get an exception on this table not having a column named: userDetails_userId
@JoinColumn(name = "id")
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private UserDetails userDetails;
}
import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.Size;
@Data
@Entity(name = "user_details")
public class UserDetails {
@Id
private Long userId;
@Column(unique = true)
@Size(min = 1, max = 100)
private String firstName;
@Column(unique = true)
@Size(min = 1, max = 100)
private String lastName;
}

当我尝试保留一个新用户时,我有一个用户对象,其中包含除 user.id 和userDetail.userId之外的所有生成值。当我尝试坚持这一点时,我得到的错误如下:

"org.springframework.orm.jpa.JpaSystemException: ids for this class must be manually assigned before calling save(): com.app.entity.UserDetails; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.app.UserDetails

请注意,为了保存用户实体,我创建了此接口:

public interface UserRepository extends JpaRepository<User, Long> { }

我使用提供的保存方法。

...
@Autowired
private UserRepository userRepository;
...
public ResponseEntity<HttpStatus> addUser(User user) {
userRepository.save(user);
return ResponseEntity.ok(HttpStatus.OK);
}

保存前的对象如下所示:

User(id=null, username=test, userDetails=UserDetails(userId=null, firstName=test, lastName=test))

我想知道我是否可以简单地保存一个用户对象并将生成的密钥级联到 userDetail。

我应该使用另一种保存方法还是我的实体有问题?

你做事的方向错误。

@Data
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Column(unique = true)
@Size(min = 1, max = 100)
private String username;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user")
private UserDetails userDetails;
}
@Data
@Entity(name = "user_details")
public class UserDetails {
@Id
private Long userId;
@Column(unique = true)
@Size(min = 1, max = 100)
private String firstName;
@Column(unique = true)
@Size(min = 1, max = 100)
private String lastName;
@MapsId
@JoinColumn(name = "USERID")
@OneToOne(fetch = FetchType.LAZY)
private User user;
}

有了这个,您只需设置 userDetail.user 引用,JPA 将保留两个用户,为其分配一个 ID 并使用它来填充 UserDetail.id 值 - 在您的模型和数据库中。

您应该维护 user.userDetail 引用,但它对数据库行数据的影响较小,而出于对象一致性原因,它的重要性更大。

最新更新