简体   繁体   English

H2,Spring boot-JPA:使用 OffsetTime 字段检索实体的问题

[英]H2, Spring boot-JPA: Issue with retrieving entity with OffsetTime field

I have a small Spring Boot application (spring-data-jpa) with H2 database (version 1.4.200).我有一个带有 H2 数据库(版本 1.4.200)的小型 Spring Boot 应用程序(spring-data-jpa)。 I have Shift object, representing a recurring interval in time:我有 Shift 对象,代表一个重复的时间间隔:

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Shift {
    @Id
    @GeneratedValue
    private Long id;
    @Column(name = "start_time", columnDefinition = "TIME WITH TIME ZONE")
    private OffsetTime startTime;
    @Column(name = "end_time", columnDefinition = "TIME WITH TIME ZONE")
    private OffsetTime endTime;

    public Shift (OffsetTime startTime, OffsetTime endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
    }
}
@RestController
@RequiredArgsConstructor
public class Controller {

    private final ShiftRepository shiftRepository;
    @RequestMapping("/")
    public Shift index() {
        return shiftRepository.getById(1L);
    }

}
public interface ShiftRepository extends JpaRepository<Shift, Long> {
}
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}
@Configuration
public class LoadDatabase {
    @Bean
    CommandLineRunner initUserTable(ShiftRepository repository) {
        return args -> repository
                .save(
                        new Shift(OffsetTime.parse("10:15:30+00:00"), OffsetTime.parse("11:25:30+00:00")));
    }}

Retrieving it leads to:检索它会导致:

Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "java.lang.NullPointerException: Cannot invoke ""org.h2.engine.CastDataProvider.currentTimestamp()"" because ""<parameter1>"" is null" [50000-200] at org.h2.message.DbException.getJdbcSQLException(DbException.java:505) ~[h2-1.4.200.jar:1.4.200] at org.h2.message.DbException.getJdbcSQLException(DbException.java:429) ~[h2-1.4.200.jar:1.4.200] at org.h2.message.DbException.get(DbException.java:194) ~[h2-1.4.200.jar:1.4.200] at org.h2.message.DbException.convert(DbException.java:347) ~[h2-1.4.200.jar:1.4.200] at org.h2.message.DbException.toSQLException(DbException.java:319) ~[h2-1.4.200.jar:1.4.200] at org.h2.message.TraceObject.logAndConvert(TraceObject.java:366) ~[h2-1.4.200.jar:1.4.200] at org.h2.jdbc.JdbcResultSet.getTime(JdbcResultSet.java:480) ~[h2-1.4.200.jar:1.4.200] at com.zaxxer.hikari.pool.HikariProxyResultSet.getTime(HikariProxyResultSet.java) ~[HikariCP-3.4.5.jar:na] at org.hibernate.type.descriptor.sql.TimeT原因:org.h2.jdbc.JdbcSQLNonTransientException:一般错误:“java.lang.NullPointerException:无法调用”“org.h2.engine.CastDataProvider.currentTimestamp()”,因为“<parameter1>”为空”[ 50000-200] 在 org.h2.message.DbException.getJdbcSQLException(DbException.java:505) ~[h2-1.4.200.jar:1.4.200] 在 org.h2.message.DbException.getJdbcSQLException(DbException.java: 429)~[h2-1.4.200.jar:1.4.200] at org.h2.message.DbException.get(DbException.java:194)~[h2-1.4.200.jar:1.4.200] at org.h2.message.DbException.get(DbException.java:194) h2.message.DbException.convert(DbException.java:347) ~[h2-1.4.200.jar:1.4.200] at org.h2.message.DbException.toSQLException(DbException.java:319) ~[h2-1.4 .200.jar:1.4.200] 在 org.h2.message.TraceObject.logAndConvert(TraceObject.java:366) ~[h2-1.4.200.jar:1.4.200] 在 org.h2.jdbc.JdbcResultSet.getTime (JdbcResultSet.java:480) ~[h2-1.4.200.jar:1.4.200] at com.zaxxer.hikari.pool.HikariProxyResultSet.getTime(HikariProxyResultSet.java) ~[HikariCP-3.4.5.jar:na]在 org.hibernate.type.descriptor.sql.TimeT ypeDescriptor$2.doExtract(TimeTypeDescriptor.java:84) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:257) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:243) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:329) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:3130) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.loader.plan.exec.process.int ypeDescriptor$2.doExtract(TimeTypeDescriptor.java:84) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java: 47) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] 在 org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:257) ~[hibernate-core-5.4.31.Final .jar:5.4.31.Final] 在 org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] 在 org.hibernate .type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:243) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:329) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:3130) ~[hibernate-core-5.4.31.Final .jar:5.4.31.Final] 在 org.hibernate.loader.plan.exec.process.int ernal.EntityReferenceInitializerImpl.loadFromResultSet(EntityReferenceInitializerImpl.java:342) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] ... 73 common frames omitted ernal.EntityReferenceInitializerImpl.loadFromResultSet(EntityReferenceInitializerImpl.java:342) ~[hibernate-core-5.4.31.Final.jar:5.4.31.Final] ...省略了73个常用帧

In debugger I see that indeed there is no timezone set:在调试器中,我看到确实没有设置时区: 在此处输入图像描述

My application.properties which could be relevant:我的 application.properties 可能相关:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

# Enabling H2 Console
spring.h2.console.enabled=true

# Custom H2 Console URL
spring.h2.console.path=/h2

Relevant lines from pom.xml: pom.xml 中的相关行:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>15</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

Do I need to use some custom converter for TIME WITH TIME ZONE database type and OffsetTime Java type?我是否需要为 TIME WITH TIME ZONE 数据库类型和 OffsetTime Java 类型使用一些自定义转换器?

It works without any exception when I change type to:当我将类型更改为:

    @Column(name = "start_time", columnDefinition = "TIME")
    private OffsetTime startTime;
    @Column(name = "end_time", columnDefinition = "TIME")
    private OffsetTime endTime;

Evgenij Ryazanov's comment above was quite helpful. Evgenij Ryazanov 的上述评论很有帮助。 I was having the same problem and was able to fix it by downgrading the version of H2, so I am elevating it here to an answer.我遇到了同样的问题,并且能够通过降级 H2 的版本来解决它,所以我在这里将其提升为答案。

In your pom.xml , update to:在您的pom.xml中,更新为:

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <!-- There is a bug with 1.4.200 and retrieving dates back from the DB -->
        <version>1.4.199</version>
    </dependency>

Spring Boot changed from 1.4.199 in version 2.1.10 . Spring Boot在 2.1.10 版本中从 1.4.199 更改。 Spring Boot 2.7 uses the new 2.x version of H2. Spring Boot 2.7 使用了新的 2.x 版本的 H2。 Presumably that would also be a fix, but I have not tried that out.大概这也是一个修复,但我还没有尝试过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM