简体   繁体   English

JPA 一对一关系的级联动作

[英]JPA cascade actions on one-to-one relationship

I have the following question regarding one to one relationships (and I guess one to many also):我有以下关于一对一关系的问题(我猜也是一对多):

Let's suppose I have the following tables:假设我有以下表格:

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)
);

As you can see the two tables share the same primary key.如您所见,这两个表共享相同的主键。 Now the entities I created are the following:现在我创建的实体如下:

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;

}

When I try to persist a new user I have a user object with all the values generated except of the user.id and the userDetail.userId.当我尝试保留一个新用户时,我有一个用户 object,其中生成了除 user.id 和 userDetail.userId 之外的所有值。 When I try to persist this the error I get is the following:当我尝试坚持这一点时,我得到的错误如下:

"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

Note that to save a User entity I created this interface:请注意,为了保存用户实体,我创建了这个界面:

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

and I use the save method provided.我使用提供的保存方法。

    ...

    @Autowired
    private UserRepository userRepository;

    ...

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

the object before saving looks like this:保存前的 object 如下所示:

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

I was wondering if I can simply save a user object and cascade the generated key to the userDetail.我想知道我是否可以简单地保存用户 object 并将生成的密钥级联到 userDetail。

Should I use another approach for saving or there is something wrong with my entities?我应该使用另一种方法进行保存还是我的实体有问题?

You've done things from the wrong direction.你做错了方向。

@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;
}

With this, you can just set the userDetail.user reference and JPA will persist both the user, assign it a ID and use that to populate the UserDetail.id value for you - in your model and in the database.有了这个,您只需设置 userDetail.user 引用,JPA 将保留两个用户,为其分配一个 ID 并使用它为您填充 UserDetail.id 值 - 在您的 model 和数据库中。

You should maintain the user.userDetail reference, but it is less consequential to the database row data and more for object consistency reasons.您应该维护 user.userDetail 引用,但由于 object 一致性原因,它对数据库行数据的影响较小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM