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

Spring Boot 2.7.1 R2DBC在H2 MSSQL兼容模式下findById报LIMIT语法错误

问题说明

将基于Spring Boot 2.6.9开发的应用升级至2.7.x版本线(当前使用2.7.1)时,测试阶段采用开启MS SQL Server兼容模式的H2内存数据库,调用ReactiveCrudRepository的findById方法会抛出SQL语法错误,错误提示生成的查询语句末尾包含MSSQL不支持的LIMIT 2子句。

  • 2.6.9版本下相同代码与配置测试执行正常
  • 2.7.1版本下执行./mvnw clean test可稳定复现问题

核心配置与代码如下:

  1. 测试环境application.yml配置
spring:
  r2dbc:
    url: r2dbc:h2:mem:///testdb?options=MODE=MSSQLServer;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
  1. 初始化脚本schema.sql
CREATE SCHEMA IF NOT EXISTS [dbo];
CREATE TABLE IF NOT EXISTS [dbo].[CUSTOMER] (
    id INTEGER GENERATED BY DEFAULT AS IDENTITY,
    name VARCHAR(255) NOT NULL,
    CONSTRAINT PK__otp__D444C58FB26C6D28 PRIMARY KEY (id)
);
  1. 实体类定义
@Table("[dbo].[CUSTOMER]")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CustomerEntity {
    @Id
    @Column("id")
    private Integer id;
    @Column("name")
    private String name;
}
  1. Repository接口定义
public interface CustomerRepository extends ReactiveCrudRepository<CustomerEntity, Integer> {
}
  1. 触发异常的测试代码
@SpringBootTest
@RequiredArgsConstructor
@TestConstructor(autowireMode = ALL)
class BootH2ApplicationTests {
    private final CustomerRepository customerRepository;
    @Test
    void shouldSaveAndLoadUsers() {
        CustomerEntity joe = customerRepository.save(new CustomerEntity(null, "Joe")).block();
        customerRepository.findById(joe.getId()).block();
    }
}

抛出的核心异常:

Caused by: io.r2dbc.spi.R2dbcBadGrammarException: 
Syntax error in SQL statement "SELECT [dbo].[CUSTOMER].* FROM [dbo].[CUSTOMER] WHERE [dbo].[CUSTOMER].id = $1 [*]LIMIT 2"; SQL statement:
SELECT [dbo].[CUSTOMER].* FROM [dbo].[CUSTOMER] WHERE [dbo].[CUSTOMER].id = $1 LIMIT 2 [42000-214]
根因分析

异常来自Spring Data R2DBC的方言识别逻辑变更:

  • Spring Boot 2.6.x绑定的Spring Data R2DBC 1.5.x版本,单条查询自动添加行数限制时,可正确识别H2的MSSQL兼容模式,生成SQL Server支持的TOP 2语法
  • Spring Boot 2.7.x绑定的Spring Data R2DBC 2.0.x版本,R2DBC方言自动检测逻辑未读取到H2连接的兼容模式参数,默认使用H2原生方言,生成了MSSQL模式不支持的LIMIT子句,最终触发语法错误。
    该问题不属于H2数据库缺陷,是框架方言识别逻辑的适配问题。
修复方案

方案1:配置文件强制指定MSSQL方言(推荐)

无需修改业务代码,直接在测试配置中跳过方言自动检测,强制使用SQL Server方言,修改application.yml即可:

spring:
  r2dbc:
    url: r2dbc:h2:mem:///testdb?options=MODE=MSSQLServer;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    properties:
      dialect: mssql

配置生效后,框架生成单条查询时会自动拼接TOP 2语法,完全适配H2的MSSQL兼容模式。

方案2:手动注册方言Bean

如果配置指定方言不生效,可以在测试配置类中手动注册SQL Server方言Bean覆盖默认实现:

@Configuration
public class R2dbcTestConfig {
    @Bean
    public R2dbcDialect r2dbcDialect() {
        return SqlServerDialect.INSTANCE;
    }
}

方案3:升级驱动版本

旧版本r2dbc-h2驱动未向上层上报兼容模式对应的数据库类型,将H2、r2dbc-h2升级到最新稳定版可修复自动识别逻辑:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>test</scope>
    <version>2.1.214</version>
</dependency>
<dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-h2</artifactId>
    <scope>test</scope>
    <version>1.0.0.RELEASE</version>
</dependency>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:57:17