一尘不染

Spring Boot中的TransientPropertyValueException

hibernate

LoginCredential上课:

@Data
@Entity
public class LoginCredential implements Serializable {
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   Long userID;
   String eMail;
   String passwordHash;
   @GeneratedValue(strategy = GenerationType.AUTO)
   @OneToOne(mappedBy = "loginCredential", fetch = FetchType.LAZY)
   User user;
}

这是我的User课:

@Data
@Entity
public class User {
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   Long userID;
   @OneToOne(fetch = FetchType.LAZY,targetEntity = LoginCredential.class)
   @JoinColumn(name = "userID",referencedColumnName = "userID")
   private LoginCredential loginCredential;
}

而且我LoginCredentialControllerPOST -ing方法很简单:

@PostMapping("/login")
LoginCredential newLoginCredential(@RequestBody LoginCredential newLoginCredential) {
    logger.debug(newLoginCredential);
    LoginCredential a=repository.save(newLoginCredential);
    logger.debug(a);
    return a;
}

现在,当我尝试此命令时: curl -X POST -H "Content-Type: application/json" -d "{ \"email\": \"1\"}" http://localhost:8080/login

我得到一个LoginCredential没有任何错误的user字段,值得一提null

这就是为什么我尝试此命令的原因 curl -X POST -H "Content-Type: application/json" -d "{ \"email\": \"1\",\"user\":{} }" http://localhost:8080/login

这给了我错误的说法:

{
  "status" : 500,
  "error" : "Internal Server Error",
  "message" : "org.hibernate.TransientPropertyValueException: object

references an unsaved transient instance - save the transient instance
before flushing : com.mua.cse616.Model.LoginCredential.user ->
com.mua.cse616.Model.User; org.hibernate.TransientPropertyValueException:
object references an unsaved transient instance - save the transient
instance before flushing : com.mua.cse616.Model.LoginCredential.user ->
com.mua.cse616.Model.User”,
“trace”:....
}

Application.properties

pom.xml


阅读 243

收藏
2020-06-20

共1个答案

一尘不染

你有三个问题

  1. 缺少从保存cascade触发User实体创建的选项LoginCredential
  2. 由于缺乏@MapsId对标注User,让他们共享相同的ID,否则LoginCredential,创造了其User将有不同的ID值两者都有@GeneratedValue(strategy = GenerationType.AUTO)自己的@Id
  3. 没有设置双方的关系…

为了解决所有问题,您需要将实体更改为以下内容(我还删除了一些无用的注释和值);

@Data
@Entity
public class User {

    @Id
    Long userID;

    @JsonBackReference
    @MapsId
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "userID", referencedColumnName = "userID")
    @ToString.Exclude
    private LoginCredential loginCredential;
}

@Data
@Entity
public class LoginCredential {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long userID;
    String eMail;
    String passwordHash;

    @JsonManagedReference
    @OneToOne(mappedBy = "loginCredential", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    private User user;
}

在最终确定端点之前,还需要设置关系的两端;

Optional.ofNullable(loginCredential.getUser())
        .ifPresent(user -> user.setLoginCredential(loginCredential));
loginCredentialRepo.save(loginCredential);
2020-06-20