Spring Boot – 测试仓库 – 引用完整性约束违规

huangapple go评论99阅读模式
英文:

Spring Boot - testing repository - Referential integrity constraint violation

问题

I see that you're encountering a "Referential integrity constraint violation" error in your Spring Boot app when testing your repositories. This error typically occurs when there's a foreign key constraint violation, meaning that a foreign key value in one table does not exist in the referenced table.

In your case, it seems to be related to the POST_USER_ID foreign key in the POST table, which references the USERS table. Here are a few things to check:

  1. Make sure that you have a user with the ID you're trying to reference (in this case, 11) in your test database. You can double-check your FakeDataSet.getFakeUser() method to ensure it's creating a user with the correct ID.

  2. Verify that the POST_USER_ID in the POST table matches the USER_ID in the USERS table correctly. Ensure that both columns have the same data type.

  3. Check if there are any database constraints or triggers that might affect this relationship.

  4. Review your data initialization and test steps to ensure you're creating and persisting entities in the correct order.

  5. Make sure that your test database is properly configured and set up for running JPA tests.

Without the full context of your application and database schema, it's challenging to pinpoint the exact issue, but these are common areas to investigate when encountering referential integrity constraint violations in JPA-based applications.

英文:

I've got a problem that I was struggling for a while. I'm trying to test repository of my Spring Boot app, but unfortunelly when i was sure how to test repositories I stucked here getting an erorr "Naruszenie więzów integralności" which means "Referential integrity constraint violation". I thing I tried most of solutions that I found on the stack internet, but none of them words for me ;/.
I have got an error like below:

  1. 17:42:20.639 [main] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Naruszenie więzów integralności: "FKKKTWEXQ2WLBTEVF2AXEQH8ANX: PUBLIC.POST FOREIGN KEY(POST_USER_ID) REFERENCES PUBLIC.USERS(USER_ID) (11)"
  2. Referential integrity constraint violation: "FKKKTWEXQ2WLBTEVF2AXEQH8ANX: PUBLIC.POST FOREIGN KEY(POST_USER_ID) REFERENCES PUBLIC.USERS(USER_ID) (11)"; SQL statement:
  3. insert into post (data, date, description, imagine_name, imagine_type, post_user_id, tittle, post_id) values (?, ?, ?, ?, ?, ?, ?, ?) [23506-200]
  4. 17:42:20.641 [main] DEBUG org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl - JDBC transaction marked for rollback-only (exception provided for stack trace)
  5. java.lang.Exception: exception just for purpose of providing stack trace
  6. at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.markRollbackOnly(JdbcResourceLocalTransactionCoordinatorImpl.java:324)
  7. at org.hibernate.engine.transaction.internal.TransactionImpl.markRollbackOnly(TransactionImpl.java:203)
  8. at org.hibernate.internal.AbstractSharedSessionContract.markForRollbackOnly(AbstractSharedSessionContract.java:396)
  9. at org.hibernate.internal.ExceptionConverterImpl.handlePersistenceException(ExceptionConverterImpl.java:297)
  10. at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
  11. at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
  12. at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
  13. at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1364)
  14. at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1347)
  15. at org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager.flush(TestEntityManager.java:171)
  16. at com.company.art.repository.PostRepositoryTests.findByPostUser_Id_One(PostRepositoryTests.java:45)
  17. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  18. ...

And that's my code:

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration(classes = ArtApplication.class, loader = AnnotationConfigContextLoader.class)
  3. @DataJpaTest
  4. public class PostRepositoryTests {
  5. @Autowired
  6. private TestEntityManager entityManager;
  7. @Autowired
  8. private PostRepository postRepository;
  9. @Test
  10. public void findByPostUser_Id_One(){
  11. //arrange
  12. Post post = new Post();
  13. User user = FakeDataSet.getFakeUser();
  14. post.setPostUser(user);
  15. Integer expected = 1;
  16. entityManager.merge(FakeDataSet.getFakeUser());
  17. entityManager.flush();
  18. entityManager.merge(post);
  19. entityManager.flush(); // <----- line with error
  20. //act
  21. List<Post> found = postRepository.findByPostUser_Id(FakeDataSet.getFakeUser().getId());
  22. //assert
  23. assertThat(found.size()).isEqualTo(expected);
  24. }
  25. }

Repository:

  1. @Repository
  2. public interface PostRepository extends JpaRepository<Post, Integer> {
  3. List<Post> findByPostUser_Id(Integer id);
  4. }

My fake data class:

  1. public class FakeDataSet {
  2. public static User getFakeUser(){
  3. User user = new User();
  4. user.setId(11);
  5. user.setActive(true);
  6. user.setUserName("TheTest");
  7. user.setPassword("Password");
  8. user.setEmail("test@test.com");
  9. user.setName("Test");
  10. user.setLastName("Testing");
  11. return user;
  12. }
  13. public static Post getFakePost(){
  14. Post post = new Post();
  15. post.setTittle("Title");
  16. post.setId(1);
  17. post.setImagineType("image/png");
  18. post.setPostUser(FakeDataSet.getFakeUser());
  19. post.setData(new byte[5]);
  20. post.setImagineName("Image");
  21. post.setDate(Calendar.getInstance());
  22. post.setDescription("Description");
  23. return post;
  24. }
  25. }

Model classes:

  1. @AllArgsConstructor
  2. @NoArgsConstructor
  3. @Entity
  4. @Table(name = "post")
  5. public class Post {
  6. @Id
  7. @GeneratedValue(strategy = GenerationType.AUTO)
  8. @Column(name = "post_id")
  9. private Integer id;
  10. @ManyToOne(fetch = FetchType.LAZY)
  11. @JoinColumn(name = "post_user_id")
  12. private User postUser;
  13. @CreationTimestamp
  14. @Temporal(TemporalType.TIMESTAMP)
  15. @Column(name = "date")
  16. private Calendar date;
  17. @Column(name = "imagine_name")
  18. private String imagineName;
  19. @Column(name = "imagine_type")
  20. private String imagineType;
  21. @Lob
  22. private byte[] data;
  23. @Column(name = "description", length = 500)
  24. @Length(max = 500)
  25. private String description;
  26. @Column(name = "tittle", length = 30)
  27. @Length(max = 30)
  28. private String tittle;
  29. @Nullable
  30. @OneToMany(mappedBy = "likedPost", cascade = CascadeType.ALL, orphanRemoval = true)
  31. private Set<PostLikes> postLikes;
  32. @Transient
  33. private MultipartFile file;
  34. }
  1. @Data
  2. @Builder
  3. @AllArgsConstructor
  4. @NoArgsConstructor
  5. @Entity
  6. @Table(name = "users")
  7. public class User {
  8. @Id
  9. @GeneratedValue(strategy = GenerationType.AUTO)
  10. @Column(name = "user_id")
  11. private int id;
  12. @Column(name = "user_name")
  13. @Length(min = 5, message = "*Your user name must have at least 5 characters")
  14. @NotEmpty(message = "*Please provide a user name")
  15. private String userName;
  16. @Column(name = "email")
  17. @Email(message = "*Please provide a valid Email")
  18. @NotEmpty(message = "*Please provide an email")
  19. private String email;
  20. @Column(name = "password")
  21. @Length(min = 5, message = "*Your password must have at least 5 characters")
  22. @NotEmpty(message = "*Please provide your password")
  23. private String password;
  24. @Column(name = "name")
  25. @NotEmpty(message = "*Please provide your name")
  26. private String name;
  27. @Column(name = "last_name")
  28. @NotEmpty(message = "*Please provide your last name")
  29. private String lastName;
  30. @Column(name = "active")
  31. private Boolean active;
  32. @ManyToMany(cascade = CascadeType.MERGE)
  33. @JoinTable(name = "users_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
  34. private Set<Role> roles;
  35. @OneToMany(mappedBy = "postUser", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
  36. private Set<Post> posts;
  37. @OneToMany(mappedBy = "userThatLike", cascade = CascadeType.ALL, orphanRemoval = true)
  38. private Set<PostLikes> postsLiked;
  39. @Column(name = "is_banned")
  40. private boolean isBanned;
  41. }

Do you have any idea what I messed up?
Thank for any tip! ;D

答案1

得分: 1

Your user id is auto generated, change your test to the following

@Test
public void findByPostUser_Id_One(){
//arrange
Post post = new Post();
User user = FakeDataSet.getFakeUser();
post.setPostUser(user);
Integer expected = 1;
entityManager.merge(user);
entityManager.flush();

  1. entityManager.merge(post);
  2. entityManager.flush(); // <----- line with error
  3. //act
  4. List<Post> found = postRepository.findByPostUser_Id(FakeDataSet.getFakeUser().getId());
  5. //assert
  6. assertThat(found.size()).isEqualTo(expected);

}

英文:

Your user id is auto generated, change your test to the following

  1. @Test
  2. public void findByPostUser_Id_One(){
  3. //arrange
  4. Post post = new Post();
  5. User user = FakeDataSet.getFakeUser();
  6. post.setPostUser(user);
  7. Integer expected = 1;
  8. entityManager.merge(user);
  9. entityManager.flush();
  10. entityManager.merge(post);
  11. entityManager.flush(); // <----- line with error
  12. //act
  13. List<Post> found = postRepository.findByPostUser_Id(FakeDataSet.getFakeUser().getId());
  14. //assert
  15. assertThat(found.size()).isEqualTo(expected);
  16. }

huangapple
  • 本文由 发表于 2020年8月12日 00:22:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/63362359.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定