4

When trying to update spring-boot from version 2.1.12 to 2.2.4 got stuck on DataIntegrityViolationException when try to insert multiple objects into MySQL using JPA.

Example object:

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
@Table(name = "user")public class User {

    @Id
    @Column(name = "id")
    @JsonProperty("id")
    private String id;

    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL)
    @JsonProperty("status")
    private UserStatus status;

}

And user status:

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "user_status")
public class UserStatus {

    @Id
    @Column(name = "id")
    @JsonProperty("id")
    private String id;

    public UserStatus(String userId) {
        this.id = userId;
    }

}

To insert object to mysql I use default jpa repository:

@Repository
public interface UserRepository extends JpaRepository<User, String> { 
}

With spring-boot-2.1.x userRepository.save(user) works fine but with 2.2.x it raises this exception:

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

With this details in log:

Cannot add or update a child row: a foreign key constraint fails (`test`.`user_status`, CONSTRAINT `user_status_ibfk_1` FOREIGN KEY (`id`) REFERENCES `user` (`id`) ON DELETE CASCADE)

If enable spring.jpa.show-SQL: true I found out that with spring-boot-2.2.x no insertion on User entity is happening but with old spring it is.

I didn't find any major change in spring-boot connecting to hibernate as well as no major change in hibernate itself after the corresponding update. Is there anything updated which is not described in release notes?

Anton
  • 43
  • 1
  • 4
  • Are you using a `spring-boot-starter-data-jpa` [starter](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-starter)? – Boris Feb 13 '20 at 12:48
  • I never understand why Spring Boot users immediately go for JPA when JdbcTemplate is available, especially for a simple schema like this. – duffymo Feb 13 '20 at 14:20
  • @duffymo Me too, but it is legacy code which we have to support for some time :( – Anton Feb 13 '20 at 14:50
  • @Anton does my answer help you, because it's very likely that it's your case? Share your thougths please to solve your problem anyway – Eugene Kortov Feb 14 '20 at 07:19
  • @EugeneKortov Thank you very much, it has finally helped. To use it I had to slightly change the structure of UserStatus object, adding reference to User object inside of UserStatus object. Then your solution worked perfectly find. Apparently, we had it done all wrong in out project. – Anton Jun 08 '20 at 13:03

1 Answers1

2

spring-boot 2.1.12 uses Hibernate 5.3.15.Final and spring-boot 2.2.4 uses Hibernate 5.4.10.Final

Your issue seems similar to Hibernate issues HHH-13413 HHH-13171

The reason is in the fix HHH-12436 which was introduced in 5.4.0.CR1 so since then one-to-one mappings don’t work when @OneToOne(mappedBy ="") didn’t provided.

And as I understood from disscussions in JIRA it's not a bug now. There was a bug and they fixed it like so. I guess there is some misunderstanding with @PrimaryKeyJoinColumn so people doesn't use it right.

I guess this will solve the problem

@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
@JsonProperty("status")
private UserStatus status;
Eugene Kortov
  • 445
  • 6
  • 17