从H2数据库读取TINYINT值时出现MappingException,试图将其转换为boolean/Boolean。

huangapple go评论88阅读模式
英文:

Getting MappingException when reading TINYINT value from H2 database as boolean/Boolean

问题

Here's the translated code you provided:

我正在使用R2DBC H2进行集成测试我的响应式应用程序基于Spring Webflux和Java)。

版本

 - 驱动程序io.r2dbc:r2dbc-h2:0.8.4.RELEASESpring Boot 2.3.2.RELEASE
 - Java11
 - 操作系统Mac

我定义了一个如下所示的表

```sql
CREATE TABLE `prep_task` (
  `id` SERIAL,
  `external_id` VARCHAR(45) NOT NULL,
  `name` VARCHAR(45) NOT NULL,
  `description` VARCHAR(100) NULL,
  `is_active` TINYINT,
  PRIMARY KEY (`id`)
);

以及相应的实体:

@Table("prep_task")
public class PrepTaskEntity implements Persistable<Long> {
  @Id
  @Column("id")
  private Long id;

  @Column("external_id")
  private String externalId;

  @Column("name")
  private String name;

  @Column("description")
  private String description;

  @Column("is_active")
  private boolean isActive;

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getExternalId() {
    return externalId;
  }

  public void setExternalId(String externalId) {
    this.externalId = externalId;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  public boolean isActive() {
    return isActive;
  }

  public void setActive(boolean active) {
    isActive = active;
  }

  @Override
  public boolean isNew() {
    return id == null;
  }
}

在保存PrepTaskEntity时没有问题,但在尝试读取时出现以下错误

org.springframework.data.mapping.MappingException: 无法从结果集中读取属性 @org.springframework.data.relational.core.mapping.Column(value="is_active")private java.lang.Boolean com.example.demosvc.persistence.entities.PrepTaskEntity.isActive 
	at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.readFrom(MappingR2dbcConverter.java:172) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
	抑制reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
错误发生在以下位置
	|_ checkpoint  处理程序 com.example.demosvc.controllers.PrepTaskController#getPrepTasksForGivenBU(String) [DispatcherHandler]
	|_ checkpoint  com.example.demosvc.filters.TenancyContextFilter [DefaultWebFilterChain]
	|_ checkpoint  HTTP GET "/sites/BU-002/prepTasks" [ExceptionHandlingWebHandler]
堆栈跟踪
		at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.readFrom(MappingR2dbcConverter.java:172) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
		at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.read(MappingR2dbcConverter.java:133) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
		at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.read(MappingR2dbcConverter.java:116) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
		at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:46) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
		at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:29) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
...

只是提供信息,我正在将H2的连接模式设置为MySQL。

@Configuration
@Profile(Application.Profiles.INTEGRATION_TEST)
public class H2ConnectionConfig extends AbstractR2dbcConfiguration {

  private final R2dbcConfigProperties r2dbcConfigProperties;

  @Autowired
  public H2ConnectionConfig(R2dbcConfigProperties r2dbcConfigProperties) {
    this.r2dbcConfigProperties = r2dbcConfigProperties;
  }

  @Override
  @Bean
  public ConnectionFactory connectionFactory() {
    RoutingConnectionFactory connectionFactory = new RoutingConnectionFactory();
    Map<String, ConnectionFactory> factories = new HashMap<>();
    H2ConnectionConfiguration.Builder configurationBuilder = H2ConnectionConfiguration.builder()
        .property(H2ConnectionOption.MODE, "MySQL")
        .property(H2ConnectionOption.DB_CLOSE_DELAY, "-1")
        .property(H2ConnectionOption.DB_CLOSE_ON_EXIT, "false");
    for (String tenant : r2dbcConfigProperties.getTenants()) {
      String databaseName = r2dbcConfigProperties.getDbPrefix() + tenant;
      factories.put(tenant, new H2ConnectionFactory(configurationBuilder.inMemory(databaseName).build()));
    }
    connectionFactory.setTargetConnectionFactories(factories);
    connectionFactory.setDefaultTargetConnectionFactory(factories.get("default"));
    return connectionFactory;
  }
}
英文:

I am using R2DBC H2 for integration testing my reactive application (which is based on Spring Webflux , Java).

Versions

  • Driver: io.r2dbc:r2dbc-h2:0.8.4.RELEASE (Spring boot 2.3.2.RELEASE)
  • Java: 11
  • OS: Mac

I have a table defined like this:

CREATE TABLE `prep_task` (
  `id` SERIAL,
  `external_id` VARCHAR(45) NOT NULL,
  `name` VARCHAR(45) NOT NULL,
  `description` VARCHAR(100) NULL,
  `is_active` TINYINT,
  PRIMARY KEY (`id`)
);

And corresponding entity:

@Table(&quot;prep_task&quot;)
public class PrepTaskEntity implements Persistable&lt;Long&gt; {
  @Id
  @Column(&quot;id&quot;)
  private Long id;

  @Column(&quot;external_id&quot;)
  private String externalId;

  @Column(&quot;name&quot;)
  private String name;

  @Column(&quot;description&quot;)
  private String description;

  @Column(&quot;is_active&quot;)
  private boolean isActive;

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getExternalId() {
    return externalId;
  }

  public void setExternalId(String externalId) {
    this.externalId = externalId;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  public boolean isActive() {
    return isActive;
  }

  public void setActive(boolean active) {
    isActive = active;
  }

  @Override
  public boolean isNew() {
    return id == null;
  }


}

No issue when saving PrepTaskEntity but when trying to read, getting the following error:

org.springframework.data.mapping.MappingException: Could not read property @org.springframework.data.relational.core.mapping.Column(value=&quot;is_active&quot;)private java.lang.Boolean com.example.demosvc.persistence.entities.PrepTaskEntity.isActive from result set!
at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.readFrom(MappingR2dbcConverter.java:172) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
|_ checkpoint ⇢ Handler com.example.demosvc.controllers.PrepTaskController#getPrepTasksForGivenBU(String) [DispatcherHandler]
|_ checkpoint ⇢ com.example.demosvc.filters.TenancyContextFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET &quot;/sites/BU-002/prepTasks&quot; [ExceptionHandlingWebHandler]
Stack trace:
at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.readFrom(MappingR2dbcConverter.java:172) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.read(MappingR2dbcConverter.java:133) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.read(MappingR2dbcConverter.java:116) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:46) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:29) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at io.r2dbc.h2.H2Result.lambda$map$0(H2Result.java:67) ~[r2dbc-h2-0.8.4.RELEASE.jar:0.8.4.RELEASE]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:73) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]
...
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Byte] to type [java.lang.Boolean]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.getPotentiallyConvertedSimpleRead(MappingR2dbcConverter.java:263) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.readValue(MappingR2dbcConverter.java:187) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.readFrom(MappingR2dbcConverter.java:169) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.read(MappingR2dbcConverter.java:133) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.MappingR2dbcConverter.read(MappingR2dbcConverter.java:116) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:46) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at org.springframework.data.r2dbc.convert.EntityRowMapper.apply(EntityRowMapper.java:29) ~[spring-data-r2dbc-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at io.r2dbc.h2.H2Result.lambda$map$0(H2Result.java:67) ~[r2dbc-h2-0.8.4.RELEASE.jar:0.8.4.RELEASE]

Just FYI I am using MySQL as connection mode for H2.

@Configuration
@Profile(Application.Profiles.INTEGRATION_TEST)
public class H2ConnectionConfig extends AbstractR2dbcConfiguration {

  private final R2dbcConfigProperties r2dbcConfigProperties;

  @Autowired
  public H2ConnectionConfig(R2dbcConfigProperties r2dbcConfigProperties) {
    this.r2dbcConfigProperties = r2dbcConfigProperties;
  }

  @Override
  @Bean
  public ConnectionFactory connectionFactory() {
    RoutingConnectionFactory connectionFactory = new RoutingConnectionFactory();
    Map&lt;String, ConnectionFactory&gt; factories = new HashMap&lt;&gt;();
    H2ConnectionConfiguration.Builder configurationBuilder = H2ConnectionConfiguration.builder()
        .property(H2ConnectionOption.MODE, &quot;MySQL&quot;)
        .property(H2ConnectionOption.DB_CLOSE_DELAY, &quot;-1&quot;)
        .property(H2ConnectionOption.DB_CLOSE_ON_EXIT, &quot;false&quot;);
    for (String tenant : r2dbcConfigProperties.getTenants()) {
      String databaseName = r2dbcConfigProperties.getDbPrefix() + tenant;
      factories.put(tenant, new H2ConnectionFactory(configurationBuilder.inMemory(databaseName).build()));
    }
    connectionFactory.setTargetConnectionFactories(factories);
    connectionFactory.setDefaultTargetConnectionFactory(factories.get(&quot;default&quot;));
    return connectionFactory;
  }

}

答案1

得分: 3

文档数据类型中提到:

> TINYINT<br>
可能的取值范围为:-128 到 127。<br>
还请参考整数文字语法。映射到 java.lang.Byte

因此,您应该将您的 DTO 类更改为如下所示:

@Table("prep_task")
public class PrepTaskEntity implements Persistable<Long> {

    // .....

    @Column("is_active")
    private Byte isActive;

    // .....

    public boolean isActive() {
        return isActive != null && isActive != 0;
    }

    public void setActive(boolean active) {
        isActive = (byte) (active ? 1 : 0);
    }

    // .....

}
英文:

The document Data Types says

> TINYINT<br>
Possible values are: -128 to 127.<br>
See also integer literal grammar. Mapped to java.lang.Byte.

So you should change you DTO class like this:

@Table(&quot;prep_task&quot;)
public class PrepTaskEntity implements Persistable&lt;Long&gt; {
// .....
@Column(&quot;is_active&quot;)
private Byte isActive;
// .....
public boolean isActive() {
return isActive != null &amp;&amp; isActive != 0;
}
public void setActive(boolean active) {
isActive = (byte) (active ? 1 : 0);
}
// .....
}

huangapple
  • 本文由 发表于 2020年8月13日 16:21:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/63390995.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定