You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JpaRepository时能否在mock场景下校验其生成的SQL查询语句?

可行实现方案

你可以通过以下两种轻量方案实现无需真实数据库的SQL校验,两种方案都不需要依赖H2、容器化数据库:

方案1:使用Datasource Proxy(通用JPA实现)

Datasource Proxy是专门用于拦截JDBC调用的工具包,可以包装数据源捕获所有生成的SQL及参数,SQL生成逻辑完全由你的JPA实现、实体映射、数据库方言决定,不需要实际建立数据库连接。

实现步骤

  1. 引入依赖(Maven示例)
<dependency>
    <groupId>net.ttddyy</groupId>
    <artifactId>datasource-proxy</artifactId>
    <version>1.9</version>
    <scope>test</scope>
</dependency>
  1. 测试环境配置代理数据源与SQL捕获逻辑
@TestConfiguration
public class SqlCaptureConfig {
    // 存储捕获到的SQL列表
    public static final List<String> CAPTURED_SQL = Collections.synchronizedList(new ArrayList<>());

    @Bean
    @Primary
    public DataSource dataSource() {
        // 用空的嵌入式数据源做兜底,不需要实际初始化库
        DataSource originalDataSource = new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.HSQL)
                .build();
        // 包装为代理数据源
        return ProxyDataSourceBuilder
                .create(originalDataSource)
                .listener(new QueryExecutionListener() {
                    @Override
                    public void beforeQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {
                        queryInfoList.forEach(q -> CAPTURED_SQL.add(q.getQuery()));
                    }
                    @Override
                    public void afterQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {}
                })
                .build();
    }
}
  1. 编写测试用例,比对SQL
@SpringBootTest
@AutoConfigureMockMvc
@Import(SqlCaptureConfig.class)
public class TControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @BeforeEach
    void clearCapturedSql() {
        SqlCaptureConfig.CAPTURED_SQL.clear();
    }

    @Test
    void testInsertSqlIsCorrect() throws Exception {
        // 执行你的原有接口测试逻辑
        mockMvc.perform(put("path")
                        .contentType(MediaType.APPLICATION_JSON)
                        .characterEncoding("UTF8")
                        .content(t)
                ).andExpect(status().isCreated())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
        // 校验生成的SQL
        assertEquals(
                "INSERT INTO t (column1, column2, column3) VALUES (?, ?, ?)",
                SqlCaptureConfig.CAPTURED_SQL.get(0)
        );
    }
}

如果需要校验参数值,Datasource Proxy也支持捕获PreparedStatement的入参,直接从QueryInfo的getParametersList获取即可

方案2:使用Hibernate StatementInspector(Hibernate作为JPA实现时可用)

如果你使用Hibernate作为JPA的实现,无需引入额外依赖,直接用Hibernate内置的StatementInspector接口即可拦截所有生成的SQL:

实现步骤

  1. 自定义StatementInspector实现
public class SqlCaptureInspector implements StatementInspector {
    public static final List<String> CAPTURED_SQL = Collections.synchronizedList(new ArrayList<>());

    @Override
    public String inspect(String sql) {
        CAPTURED_SQL.add(sql);
        return sql;
    }
}
  1. 测试配置中开启Inspector
    在application-test.properties中添加配置:
spring.jpa.properties.hibernate.session_factory.statement_inspector=com.example.test.SqlCaptureInspector
spring.jpa.hibernate.ddl-auto=none
# 配置你实际使用的数据库方言,决定SQL生成规则
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
  1. 测试用例和方案1一致,执行接口调用后直接比对CAPTURED_SQL中的内容即可。

注意事项

两种方案都不需要实际建立数据库连接,SQL生成仅依赖你的实体映射配置、数据库方言,完全符合你的测试需求。

内容的提问来源于stack exchange,提问作者Stephan Hogenboom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 19:45:04