TransientPropertyValueException в Spring Boot - PullRequest
1 голос
/ 04 октября 2019

У меня 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;
}

И мой LoginCredentialController POST -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 без каких-либо ошибок, отметим, что поле usernull.

Вот почему я попробовал эту команду 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":....
}

Приложение.properties

pom.xml

Ответы [ 3 ]

1 голос
/ 04 октября 2019

У вас есть три проблемы

  1. Отсутствие опции cascade для запуска User создания сущности из LoginCredential сохранения.
  2. Отсутствие @MapsId аннотации Userтак что они имеют один и тот же идентификатор, в противном случае LoginCredential и его созданные User будут иметь разные значения идентификатора, поскольку у них обоих @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);
0 голосов
/ 04 октября 2019

Сделать класс пользователя также сериализуемым.

0 голосов
/ 04 октября 2019

Вам не нужно @GeneratedValue для объекта пользователя

Добавить CascadeType для OneToOne

Этим вы сообщаете hibernate для сохранения пользователя в базу данных при сохранении LoginCredential.

@Data
@Entity
public class LoginCredential implements Serializable {

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   Long userID;

   String eMail;

   String passwordHash;

   @OneToOne(cascade = {CascadeType.ALL}, mappedBy = "loginCredential", fetch = FetchType.LAZY)
   User user;
}

См. Это для подробнее

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...