如何使用 querydsl 测试更新?

Posted

技术标签:

【中文标题】如何使用 querydsl 测试更新?【英文标题】:How can I test update using querydsl? 【发布时间】:2022-01-06 21:31:24 【问题描述】:

我正在尝试使用带有 querydsl 的自定义存储库来测试更新。 但它失败了,因为数据没有更新。我在调用存储库函数后尝试刷新,但它不起作用。 我认为这与某种实体管理器问题有关,但由于我是 Spring 新手,所以我不太清楚。

存储库代码:

    @Override
    public Long updateNotice(String noticeId, Notice noticeInfo) 
        UpdateClause<JPAUpdateClause> updateBuilder = queryFactory.update(notice);

        if(StringUtils.isNotEmpty(noticeInfo.getTitle())) 
            updateBuilder.set(notice.title, noticeInfo.getTitle());
        

        if(StringUtils.isNotEmpty(noticeInfo.getContents())) 
            updateBuilder.set(notice.contents, noticeInfo.getContents());
        

        if(StringUtils.isNotEmpty(noticeInfo.getTheme())) 
            updateBuilder.set(notice.theme, noticeInfo.getTheme());
        

        if (StringUtils.isNotEmpty(Integer.toString(noticeInfo.getState()))) 
            updateBuilder.set(notice.state, noticeInfo.getState());
        

        if(StringUtils.isNotEmpty(noticeInfo.getLocation())) 
            updateBuilder.set(notice.location, noticeInfo.getLocation());
        

        updateBuilder.set(notice.startDate, noticeInfo.getStartDate());
        updateBuilder.set(notice.endDate, noticeInfo.getEndDate());
        updateBuilder.set(notice.modiDate, LocalDateTime.now());

        Long count = updateBuilder
                .where(notice.noticeId.eq(noticeId))
                .execute();

        return count;
    

测试代码:

    @Test
    public void updateNoticeTest() 

        //given
        Notice titleNotice = Notice.builder()
                .title("Update notice")
                .startDate(LocalDateTime.of(2021, 10, 11, 00, 00, 00))
                .endDate(LocalDateTime.of(2021, 12, 12, 00, 00, 00))
                .build();

        List<Notice> notices = noticeRepository.findAll();
        String id = notices.get(1).getNoticeId();
        Notice notice = notices.get(1);
        log.info(notice.toString());

        //when

        Long result = noticeRepository.updateNotice(id, titleNotice);
        noticeRepository.flush();

        //then
        Notice res = noticeRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("No such notice with id " + id));
        log.info(res.toString());
        assertThat(res.getTitle()).isEqualTo("Update notice");
    

测试配置:

# Datasource settings
spring.datasource.url=jdbc:h2:mem:testdb;Mode=Oracle;DB_CLOSE_DELAY=-1
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=


# set jpa
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
#logging.level.org.hibernate.type.descriptor.sql=trace


# set log
logging.level.root=info

# set page option
# 1-based
spring.data.web.pageable.one-indexed-parameters=true
# page size = 10
spring.data.web.pageable.default-page-size=10
spring.data.web.pageable.max-page-size=1000

【问题讨论】:

【参考方案1】:

刷新没有帮助,因为它将EntityManager 收集的更改写入数据库。但是 EM 没有收集任何更改,因为您使用了更新语句,它不会更新基本上是 EM 的一级缓存。

findById 将通过一些较早的交互返回已经在一级缓存中的旧实例,可能是首先存储它们。

为了解决这个问题,你应该调用EntityManager.clear清空一级缓存

【讨论】:

以上是关于如何使用 querydsl 测试更新?的主要内容,如果未能解决你的问题,请参考以下文章

直接从querydsl更新数据时如何刷新Spring JPA?

如何在 M1 Mac 上运行 querydsl 项目测试?

QueryDsl 设置架构

如何使用 QueryDSL 构建 GenericDao?

如何使用 QueryDSL 在查询中使用 SAMPLE 关键字

如何连接多个 queryDSL 表