Spring Hibernate不会在复制时引发异常

Spring Hibernate不会在复制时引发异常,spring,hibernate,jpa,integration-testing,junit5,Spring,Hibernate,Jpa,Integration Testing,Junit5,大家好,我正在尝试实现基本的CRUD功能,但困扰我的是,CRUDepository在保存重复实体时没有抛出任何异常,您能告诉我这里缺少什么吗 我无法通过的测试如下所示: @Test void onDuplicate() { ReviewEntity duplicated = savedReviewEntity; assertEquals(savedReviewEntity.getId(), duplicated.getId());

大家好,我正在尝试实现基本的CRUD功能,但困扰我的是,CRUDepository在保存重复实体时没有抛出任何异常,您能告诉我这里缺少什么吗

我无法通过的测试如下所示:

  @Test
    void onDuplicate() {

        ReviewEntity duplicated = savedReviewEntity;

        assertEquals(savedReviewEntity.getId(), duplicated.getId());

        assertThrows(DataIntegrityViolationException.class, () -> {
            reviewRepository.save(duplicated);
        });
    }
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Getter
@Setter
@Entity
@Table(name = "reviews", indexes = { @Index(name = "reviews_unique_idx", unique = true, columnList = "movieId,reviewId") })
public class ReviewEntity {

    @Id
    @GeneratedValue
    private Integer id;

    @Version
    private Integer version;

    private Integer movieId;
    private Integer reviewId;
    private String author;
    private String subject;
    private String content;
    private String serviceAddress;
}
@ExtendWith(SpringExtension.class)
@DataJpaTest
@Transactional(propagation = NOT_SUPPORTED)
class ReviewRepositoryTest {

    public static final int BASE_MOVIE_ID = 1;
    public static final int BASE_REVIEW_ID = 2;
    @Autowired
    ReviewRepository reviewRepository;

    ReviewEntity savedReviewEntity;

    @Autowired
    EntityManager entityManager;

    @BeforeEach
    void setUp() {
        reviewRepository.deleteAll();

        ReviewEntity reviewEntity = ReviewEntity.builder()
                .movieId(BASE_MOVIE_ID)
                .reviewId(BASE_REVIEW_ID)
                .author("Fake Author")
                .content("Fake Content")
                .subject("Fake Subject")
                .serviceAddress("Fake Service Address")
                .build();

        savedReviewEntity = reviewRepository.save(reviewEntity);

        assertReview(reviewEntity, savedReviewEntity);
    }

    @Test
    void create() {
        reviewRepository.deleteAll();

        ReviewEntity reviewEntity = ReviewEntity.builder()
                .movieId(BASE_MOVIE_ID)
                .reviewId(BASE_REVIEW_ID)
                .author("Fake Author")
                .content("Fake Content")
                .subject("Fake Subject")
                .serviceAddress("Fake Service Address")
                .build();

        ReviewEntity saved = reviewRepository.save(reviewEntity);

        assertReview(reviewEntity, saved);
    }

    @Test
    void update() {

        String updatedContent = "Updated Content";

        savedReviewEntity.setContent(updatedContent);

        reviewRepository.save(savedReviewEntity);

        ReviewEntity updated = reviewRepository.findById(savedReviewEntity.getId()).get();

        assertEquals(updatedContent, updated.getContent());

    }


    @Test
    void delete() {

        reviewRepository.delete(savedReviewEntity);

        assertEquals(0, reviewRepository.count());

    }

    @Test
    void findByMovieId() {

        List<ReviewEntity> reviewEntities = reviewRepository.findByMovieId(savedReviewEntity.getMovieId());
        ReviewEntity firstEntity = reviewEntities.get(0);

        assertThat(reviewEntities, hasSize(1));
        assertReview(savedReviewEntity, firstEntity);

    }


    @Test
    void onDuplicate() {

        ReviewEntity duplicated = savedReviewEntity;

        assertEquals(savedReviewEntity.getId(), duplicated.getId());

        assertThrows(DataIntegrityViolationException.class, () -> {
            reviewRepository.save(duplicated);
        });
    }


    @Test
    void optimisticLockVerification() {
        String r1ConcurrentContent = "r1ConcurrentContent";
        String r2ConcurrentContent = "r2ConcurrentContent";

        ReviewEntity r1 = reviewRepository.findById(savedReviewEntity.getId()).get();
        ReviewEntity r2 = reviewRepository.findById(savedReviewEntity.getId()).get();

        r1.setContent(r1ConcurrentContent);
        reviewRepository.save(r1);

        try {
            r2.setContent(r2ConcurrentContent);
            reviewRepository.save(r2);

            fail("Expected an OptimisticLockingFailureException");
        } catch (OptimisticLockingFailureException e) {
            System.out.println("OptimisticLockingFailureException should be throw.");
        }

        ReviewEntity updated = reviewRepository.findById(savedReviewEntity.getId()).get();
        assertEquals(1, (int) updated.getVersion());
        assertEquals(r1ConcurrentContent, updated.getContent());
    }

    private void assertReview(ReviewEntity expected, ReviewEntity actual) {
        assertAll("Executing assertReview(..)", () -> {
            assertEquals(expected.getId(), actual.getId());
            assertEquals(expected.getVersion(), actual.getVersion());
            assertEquals(expected.getMovieId(), actual.getMovieId());
            assertEquals(expected.getReviewId(), actual.getReviewId());
            assertEquals(expected.getContent(), actual.getContent());
            assertEquals(expected.getAuthor(), actual.getAuthor());
            assertEquals(expected.getSubject(), actual.getSubject());
            assertEquals(expected.getServiceAddress(), actual.getServiceAddress());
        });
    }
}
实体的外观如下所示:

  @Test
    void onDuplicate() {

        ReviewEntity duplicated = savedReviewEntity;

        assertEquals(savedReviewEntity.getId(), duplicated.getId());

        assertThrows(DataIntegrityViolationException.class, () -> {
            reviewRepository.save(duplicated);
        });
    }
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Getter
@Setter
@Entity
@Table(name = "reviews", indexes = { @Index(name = "reviews_unique_idx", unique = true, columnList = "movieId,reviewId") })
public class ReviewEntity {

    @Id
    @GeneratedValue
    private Integer id;

    @Version
    private Integer version;

    private Integer movieId;
    private Integer reviewId;
    private String author;
    private String subject;
    private String content;
    private String serviceAddress;
}
@ExtendWith(SpringExtension.class)
@DataJpaTest
@Transactional(propagation = NOT_SUPPORTED)
class ReviewRepositoryTest {

    public static final int BASE_MOVIE_ID = 1;
    public static final int BASE_REVIEW_ID = 2;
    @Autowired
    ReviewRepository reviewRepository;

    ReviewEntity savedReviewEntity;

    @Autowired
    EntityManager entityManager;

    @BeforeEach
    void setUp() {
        reviewRepository.deleteAll();

        ReviewEntity reviewEntity = ReviewEntity.builder()
                .movieId(BASE_MOVIE_ID)
                .reviewId(BASE_REVIEW_ID)
                .author("Fake Author")
                .content("Fake Content")
                .subject("Fake Subject")
                .serviceAddress("Fake Service Address")
                .build();

        savedReviewEntity = reviewRepository.save(reviewEntity);

        assertReview(reviewEntity, savedReviewEntity);
    }

    @Test
    void create() {
        reviewRepository.deleteAll();

        ReviewEntity reviewEntity = ReviewEntity.builder()
                .movieId(BASE_MOVIE_ID)
                .reviewId(BASE_REVIEW_ID)
                .author("Fake Author")
                .content("Fake Content")
                .subject("Fake Subject")
                .serviceAddress("Fake Service Address")
                .build();

        ReviewEntity saved = reviewRepository.save(reviewEntity);

        assertReview(reviewEntity, saved);
    }

    @Test
    void update() {

        String updatedContent = "Updated Content";

        savedReviewEntity.setContent(updatedContent);

        reviewRepository.save(savedReviewEntity);

        ReviewEntity updated = reviewRepository.findById(savedReviewEntity.getId()).get();

        assertEquals(updatedContent, updated.getContent());

    }


    @Test
    void delete() {

        reviewRepository.delete(savedReviewEntity);

        assertEquals(0, reviewRepository.count());

    }

    @Test
    void findByMovieId() {

        List<ReviewEntity> reviewEntities = reviewRepository.findByMovieId(savedReviewEntity.getMovieId());
        ReviewEntity firstEntity = reviewEntities.get(0);

        assertThat(reviewEntities, hasSize(1));
        assertReview(savedReviewEntity, firstEntity);

    }


    @Test
    void onDuplicate() {

        ReviewEntity duplicated = savedReviewEntity;

        assertEquals(savedReviewEntity.getId(), duplicated.getId());

        assertThrows(DataIntegrityViolationException.class, () -> {
            reviewRepository.save(duplicated);
        });
    }


    @Test
    void optimisticLockVerification() {
        String r1ConcurrentContent = "r1ConcurrentContent";
        String r2ConcurrentContent = "r2ConcurrentContent";

        ReviewEntity r1 = reviewRepository.findById(savedReviewEntity.getId()).get();
        ReviewEntity r2 = reviewRepository.findById(savedReviewEntity.getId()).get();

        r1.setContent(r1ConcurrentContent);
        reviewRepository.save(r1);

        try {
            r2.setContent(r2ConcurrentContent);
            reviewRepository.save(r2);

            fail("Expected an OptimisticLockingFailureException");
        } catch (OptimisticLockingFailureException e) {
            System.out.println("OptimisticLockingFailureException should be throw.");
        }

        ReviewEntity updated = reviewRepository.findById(savedReviewEntity.getId()).get();
        assertEquals(1, (int) updated.getVersion());
        assertEquals(r1ConcurrentContent, updated.getContent());
    }

    private void assertReview(ReviewEntity expected, ReviewEntity actual) {
        assertAll("Executing assertReview(..)", () -> {
            assertEquals(expected.getId(), actual.getId());
            assertEquals(expected.getVersion(), actual.getVersion());
            assertEquals(expected.getMovieId(), actual.getMovieId());
            assertEquals(expected.getReviewId(), actual.getReviewId());
            assertEquals(expected.getContent(), actual.getContent());
            assertEquals(expected.getAuthor(), actual.getAuthor());
            assertEquals(expected.getSubject(), actual.getSubject());
            assertEquals(expected.getServiceAddress(), actual.getServiceAddress());
        });
    }
}
我在用积垢沉淀剂

public interface ReviewRepository extends CrudRepository<ReviewEntity, Integer> {

    @Transactional(readOnly = true)
    List<ReviewEntity> findByMovieId(int movieId);
}
public interface ReviewRepository扩展了crudepository{
@事务(只读=真)
列表findByMovieId(int movieId);
}
我想看看整个测试类,它看起来像:

  @Test
    void onDuplicate() {

        ReviewEntity duplicated = savedReviewEntity;

        assertEquals(savedReviewEntity.getId(), duplicated.getId());

        assertThrows(DataIntegrityViolationException.class, () -> {
            reviewRepository.save(duplicated);
        });
    }
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Getter
@Setter
@Entity
@Table(name = "reviews", indexes = { @Index(name = "reviews_unique_idx", unique = true, columnList = "movieId,reviewId") })
public class ReviewEntity {

    @Id
    @GeneratedValue
    private Integer id;

    @Version
    private Integer version;

    private Integer movieId;
    private Integer reviewId;
    private String author;
    private String subject;
    private String content;
    private String serviceAddress;
}
@ExtendWith(SpringExtension.class)
@DataJpaTest
@Transactional(propagation = NOT_SUPPORTED)
class ReviewRepositoryTest {

    public static final int BASE_MOVIE_ID = 1;
    public static final int BASE_REVIEW_ID = 2;
    @Autowired
    ReviewRepository reviewRepository;

    ReviewEntity savedReviewEntity;

    @Autowired
    EntityManager entityManager;

    @BeforeEach
    void setUp() {
        reviewRepository.deleteAll();

        ReviewEntity reviewEntity = ReviewEntity.builder()
                .movieId(BASE_MOVIE_ID)
                .reviewId(BASE_REVIEW_ID)
                .author("Fake Author")
                .content("Fake Content")
                .subject("Fake Subject")
                .serviceAddress("Fake Service Address")
                .build();

        savedReviewEntity = reviewRepository.save(reviewEntity);

        assertReview(reviewEntity, savedReviewEntity);
    }

    @Test
    void create() {
        reviewRepository.deleteAll();

        ReviewEntity reviewEntity = ReviewEntity.builder()
                .movieId(BASE_MOVIE_ID)
                .reviewId(BASE_REVIEW_ID)
                .author("Fake Author")
                .content("Fake Content")
                .subject("Fake Subject")
                .serviceAddress("Fake Service Address")
                .build();

        ReviewEntity saved = reviewRepository.save(reviewEntity);

        assertReview(reviewEntity, saved);
    }

    @Test
    void update() {

        String updatedContent = "Updated Content";

        savedReviewEntity.setContent(updatedContent);

        reviewRepository.save(savedReviewEntity);

        ReviewEntity updated = reviewRepository.findById(savedReviewEntity.getId()).get();

        assertEquals(updatedContent, updated.getContent());

    }


    @Test
    void delete() {

        reviewRepository.delete(savedReviewEntity);

        assertEquals(0, reviewRepository.count());

    }

    @Test
    void findByMovieId() {

        List<ReviewEntity> reviewEntities = reviewRepository.findByMovieId(savedReviewEntity.getMovieId());
        ReviewEntity firstEntity = reviewEntities.get(0);

        assertThat(reviewEntities, hasSize(1));
        assertReview(savedReviewEntity, firstEntity);

    }


    @Test
    void onDuplicate() {

        ReviewEntity duplicated = savedReviewEntity;

        assertEquals(savedReviewEntity.getId(), duplicated.getId());

        assertThrows(DataIntegrityViolationException.class, () -> {
            reviewRepository.save(duplicated);
        });
    }


    @Test
    void optimisticLockVerification() {
        String r1ConcurrentContent = "r1ConcurrentContent";
        String r2ConcurrentContent = "r2ConcurrentContent";

        ReviewEntity r1 = reviewRepository.findById(savedReviewEntity.getId()).get();
        ReviewEntity r2 = reviewRepository.findById(savedReviewEntity.getId()).get();

        r1.setContent(r1ConcurrentContent);
        reviewRepository.save(r1);

        try {
            r2.setContent(r2ConcurrentContent);
            reviewRepository.save(r2);

            fail("Expected an OptimisticLockingFailureException");
        } catch (OptimisticLockingFailureException e) {
            System.out.println("OptimisticLockingFailureException should be throw.");
        }

        ReviewEntity updated = reviewRepository.findById(savedReviewEntity.getId()).get();
        assertEquals(1, (int) updated.getVersion());
        assertEquals(r1ConcurrentContent, updated.getContent());
    }

    private void assertReview(ReviewEntity expected, ReviewEntity actual) {
        assertAll("Executing assertReview(..)", () -> {
            assertEquals(expected.getId(), actual.getId());
            assertEquals(expected.getVersion(), actual.getVersion());
            assertEquals(expected.getMovieId(), actual.getMovieId());
            assertEquals(expected.getReviewId(), actual.getReviewId());
            assertEquals(expected.getContent(), actual.getContent());
            assertEquals(expected.getAuthor(), actual.getAuthor());
            assertEquals(expected.getSubject(), actual.getSubject());
            assertEquals(expected.getServiceAddress(), actual.getServiceAddress());
        });
    }
}
@ExtendWith(SpringExtension.class)
@DataJpaTest
@事务性(传播=不受支持)
类回顾位置测试{
公共静态最终int BASE_MOVIE_ID=1;
公共静态最终int BASE_REVIEW_ID=2;
@自动连线
回顾性的回顾性的回顾性的回顾性的;
查看实体保存的视图实体;
@自动连线
实体管理器实体管理器;
@之前
无效设置(){
reviewRepository.deleteAll();
ReviewEntity ReviewEntity=ReviewEntity.builder()
.movieId(基本电影ID)
.reviewId(基本审查ID)
.作者(“假作者”)
.内容(“虚假内容”)
.主语(“假主语”)
.serviceAddress(“假服务地址”)
.build();
savedReviewEntity=reviewRepository.save(reviewEntity);
资产审查(审查实体、保存实体);
}
@试验
void create(){
reviewRepository.deleteAll();
ReviewEntity ReviewEntity=ReviewEntity.builder()
.movieId(基本电影ID)
.reviewId(基本审查ID)
.作者(“假作者”)
.内容(“虚假内容”)
.主语(“假主语”)
.serviceAddress(“假服务地址”)
.build();
ReviewEntity saved=reviewRepository.save(ReviewEntity);
资产审核(审核实体,已保存);
}
@试验
无效更新(){
String updatedContent=“更新的内容”;
savedReviewEntity.setContent(updatedContent);
reviewRepository.save(savedReviewEntity);
ReviewEntity updated=reviewRepository.findById(savedReviewEntity.getId()).get();
assertEquals(updatedContent,updated.getContent());
}
@试验
作废删除(){
reviewRepository.delete(savedReviewEntity);
assertEquals(0,reviewRepository.count());
}
@试验
void findByMovieId(){
List reviewEntities=reviewRepository.findByMovieId(savedReviewEntity.getMovieId());
ReviewEntityFirstEntity=ReviewEntitys.get(0);
资产(审查实体,规模(1));
资产审查(savedReviewEntity、firstEntity);
}
@试验
void onDuplicate(){
ReviewEntity duplicated=savedReviewEntity;
assertEquals(savedReviewEntity.getId(),duplicated.getId());
assertThrows(DataIntegrityViolationException.class,()->{
reviewRepository.save(复制);
});
}
@试验
无效优化锁验证(){
字符串r1ConcurrentContent=“r1ConcurrentContent”;
字符串r2ConcurrentContent=“r2ConcurrentContent”;
ReviewEntity r1=reviewRepository.findById(savedReviewEntity.getId()).get();
ReviewEntity r2=reviewRepository.findById(savedReviewEntity.getId()).get();
r1.设置内容(r1ConcurrentContent);
reviewRepository.save(r1);
试一试{
r2.设置内容(r2ConcurrentContent);
reviewRepository.save(r2);
失败(“预期乐观锁定失败例外”);
}捕捉(优化锁定故障异常e){
System.out.println(“应该抛出OptimisticLockingFailureException”);
}
ReviewEntity updated=reviewRepository.findById(savedReviewEntity.getId()).get();
assertEquals(1,(int)updated.getVersion());
assertEquals(r1ConcurrentContent,updated.getContent());
}
私有无效资产审查(预期审查实体,实际审查实体){
assertAll(“正在执行assertReview(..),()->{
assertEquals(预期为.getId(),实际为.getId());
assertEquals(预期为.getVersion(),实际为.getVersion());
assertEquals(预期为.getMovieId(),实际为.getMovieId());
assertEquals(预期为.getReviewId(),实际为.getReviewId());
assertEquals(预期为.getContent(),实际为.getContent());
assertEquals(预期为.getAuthor(),实际为.getAuthor());
assertEquals(预期为.getSubject(),实际为.getSubject());
assertEquals(预期为.getServiceAddress(),实际为.getServiceAddress());
});
}
}

当数据库中的插入或更新违反任何完整性约束时抛出。在您的方法中,您试图用它自己覆盖表中的一个条目,而该条目不会产生任何此类冲突。Hibernate不会在表中创建任何新条目,它只是更新它(这里使用相同的对象,因为没有更改)。

您能提供SQL模型和约束吗?我还没有任何真正的SQL数据库。作为数据库环境,我现在正在使用H2。因此,您需要在
reviews
表的
id
列上添加一个唯一的约束,除非您没有任何重复的异常。