关于一对一关系,我有以下问题(我猜也是一对多):

假设我有以下表格:

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,然后使用该ID为您填充模型和数据库中的UserDetail.id值。

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

10-04 19:23