【问题标题】:Spring Boot - testing repository - Referential integrity constraint violationSpring Boot - 测试存储库 - 违反参照完整性约束
【发布时间】:2020-08-11 16:22:43
【问题描述】:

我遇到了一个困扰了一段时间的问题。我正在尝试测试我的 Spring Boot 应用程序的存储库,但不幸的是,当我确定如何测试存储库时,我卡在这里得到一个错误“Naruszenie więzówintegrationności”,意思是“违反参照完整性约束”。我想我尝试了我在堆栈互联网上找到的大多数解决方案,但没有一个适合我;/。 我收到如下错误:

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)
    ...

这是我的代码:

@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
public interface PostRepository extends JpaRepository<Post, Integer> {
    List<Post> findByPostUser_Id(Integer id);
}

我的假数据类:

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;
    }
}

模型类:

@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;

}

你知道我搞砸了什么吗? 感谢任何提示! ;D

【问题讨论】:

    标签: java spring-boot hibernate testing


    【解决方案1】:

    您的用户 ID 是自动生成的,请将您的测试更改为以下内容

        @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);
        }
    

    【讨论】:

    • 不幸的是我之前尝试过这样的解决方案(我复制粘贴了我的一个尝试)。只是为了确保我复制了您的解决方案,但正如我预期的那样不起作用并且它打印相同的错误消息:/
    • 等等,你是对的,如果我在 FakeDataSet 中声明 id 并不重要,在这种情况下它总是 1,因为它是生成的。您的解决方案没有解决问题,但您以其他方式解决了问题。非常感谢:D
    猜你喜欢
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 2017-12-25
    相关资源
    最近更新 更多