英文:
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:
-
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 yourFakeDataSet.getFakeUser()
method to ensure it's creating a user with the correct ID. -
Verify that the
POST_USER_ID
in thePOST
table matches theUSER_ID
in theUSERS
table correctly. Ensure that both columns have the same data type. -
Check if there are any database constraints or triggers that might affect this relationship.
-
Review your data initialization and test steps to ensure you're creating and persisting entities in the correct order.
-
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:
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)"
Referential integrity constraint violation: "FKKKTWEXQ2WLBTEVF2AXEQH8ANX: PUBLIC.POST FOREIGN KEY(POST_USER_ID) REFERENCES PUBLIC.USERS(USER_ID) (11)"; SQL statement:
insert into post (data, date, description, imagine_name, imagine_type, post_user_id, tittle, post_id) values (?, ?, ?, ?, ?, ?, ?, ?) [23506-200]
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)
java.lang.Exception: exception just for purpose of providing stack trace
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.markRollbackOnly(JdbcResourceLocalTransactionCoordinatorImpl.java:324)
at org.hibernate.engine.transaction.internal.TransactionImpl.markRollbackOnly(TransactionImpl.java:203)
at org.hibernate.internal.AbstractSharedSessionContract.markForRollbackOnly(AbstractSharedSessionContract.java:396)
at org.hibernate.internal.ExceptionConverterImpl.handlePersistenceException(ExceptionConverterImpl.java:297)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1364)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1347)
at org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager.flush(TestEntityManager.java:171)
at com.company.art.repository.PostRepositoryTests.findByPostUser_Id_One(PostRepositoryTests.java:45)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
And that's my code:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ArtApplication.class, loader = AnnotationConfigContextLoader.class)
@DataJpaTest
public class PostRepositoryTests {
@Autowired
private TestEntityManager entityManager;
@Autowired
private PostRepository postRepository;
@Test
public void findByPostUser_Id_One(){
//arrange
Post post = new Post();
User user = FakeDataSet.getFakeUser();
post.setPostUser(user);
Integer expected = 1;
entityManager.merge(FakeDataSet.getFakeUser());
entityManager.flush();
entityManager.merge(post);
entityManager.flush(); // <----- line with error
//act
List<Post> found = postRepository.findByPostUser_Id(FakeDataSet.getFakeUser().getId());
//assert
assertThat(found.size()).isEqualTo(expected);
}
}
Repository:
@Repository
public interface PostRepository extends JpaRepository<Post, Integer> {
List<Post> findByPostUser_Id(Integer id);
}
My fake data class:
public class FakeDataSet {
public static User getFakeUser(){
User user = new User();
user.setId(11);
user.setActive(true);
user.setUserName("TheTest");
user.setPassword("Password");
user.setEmail("test@test.com");
user.setName("Test");
user.setLastName("Testing");
return user;
}
public static Post getFakePost(){
Post post = new Post();
post.setTittle("Title");
post.setId(1);
post.setImagineType("image/png");
post.setPostUser(FakeDataSet.getFakeUser());
post.setData(new byte[5]);
post.setImagineName("Image");
post.setDate(Calendar.getInstance());
post.setDescription("Description");
return post;
}
}
Model classes:
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "post")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "post_id")
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_user_id")
private User postUser;
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "date")
private Calendar date;
@Column(name = "imagine_name")
private String imagineName;
@Column(name = "imagine_type")
private String imagineType;
@Lob
private byte[] data;
@Column(name = "description", length = 500)
@Length(max = 500)
private String description;
@Column(name = "tittle", length = 30)
@Length(max = 30)
private String tittle;
@Nullable
@OneToMany(mappedBy = "likedPost", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<PostLikes> postLikes;
@Transient
private MultipartFile file;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id")
private int id;
@Column(name = "user_name")
@Length(min = 5, message = "*Your user name must have at least 5 characters")
@NotEmpty(message = "*Please provide a user name")
private String userName;
@Column(name = "email")
@Email(message = "*Please provide a valid Email")
@NotEmpty(message = "*Please provide an email")
private String email;
@Column(name = "password")
@Length(min = 5, message = "*Your password must have at least 5 characters")
@NotEmpty(message = "*Please provide your password")
private String password;
@Column(name = "name")
@NotEmpty(message = "*Please provide your name")
private String name;
@Column(name = "last_name")
@NotEmpty(message = "*Please provide your last name")
private String lastName;
@Column(name = "active")
private Boolean active;
@ManyToMany(cascade = CascadeType.MERGE)
@JoinTable(name = "users_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
@OneToMany(mappedBy = "postUser", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Set<Post> posts;
@OneToMany(mappedBy = "userThatLike", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<PostLikes> postsLiked;
@Column(name = "is_banned")
private boolean isBanned;
}
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();
entityManager.merge(post);
entityManager.flush(); // <----- line with error
//act
List<Post> found = postRepository.findByPostUser_Id(FakeDataSet.getFakeUser().getId());
//assert
assertThat(found.size()).isEqualTo(expected);
}
英文:
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();
entityManager.merge(post);
entityManager.flush(); // <----- line with error
//act
List<Post> found = postRepository.findByPostUser_Id(FakeDataSet.getFakeUser().getId());
//assert
assertThat(found.size()).isEqualTo(expected);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论