【问题标题】:HsqlException: type not found or user lacks privilege: DATETIMEOFFSETHsqlException:找不到类型或用户缺少权限:DATETIMEOFFSET
【发布时间】:2019-09-09 02:42:26
【问题描述】:

我有一个 Java 8、Spring Boot 2 应用程序,其中 JPA 实体连接到 MS SQL Server 数据库。我正在尝试使用 HSQLDB (2.3.3) 创建集成测试,如果我不包含审计信息(创建日期、上次更新等),它可以正常工作。

这是我收到的错误消息:

Caused by: org.hsqldb.HsqlException: type not found or user lacks privilege: DATETIMEOFFSET

我了解“未找到类型或用户缺少权限”错误是一般性的,可能由多种原因引起。在这种情况下,我知道如果不是尝试将 datetimeoffset 列添加到表中,一切都会正常运行。

在网上寻找答案时,我发现this documentation 至少支持一些 MS SQL 日期/时间类型和函数,但this (two-year-old) answer 表明 HSQLDB 对 MS SQL 的支持有限。我还没有找到任何专门讨论与 datetimeoffset 数据类型相关的 HSQLDB 的文档。

我的表创建和数据插入脚本:

    DROP SCHEMA TEST IF EXISTS;
    CREATE SCHEMA TEST;

    CREATE TABLE TEST.Example (
      ID int IDENTITY NOT NULL,
      Name nvarchar(30) NOT NULL,
      Description nvarchar(1000),
      CreatedDate datetimeoffset(7) NOT NULL
    );

    INSERT INTO TEST.Example (ID, Name, Description, CreatedDate) 
    VALUES (1, 'First', 'This is the first example.', '2019-04-18 12:00:00 -05:00');

我的数据源配置:

    config:
      datasource:
        jdbc-url: jdbc:hsqldb:mem:testdb;sys.syntax_mss=true
        driver-class-name: org.hsqldb.jdbc.JDBCDriver
        validation-query: SELECT 1
        test-on-borrow: false
        test-while-idle: true
        time-between-eviction-runs-millis: 60000
        max-active: 10

我的实体:

    @Data
    @Entity
    @Table(name = "Example", schema = "TEST")
    public class ExampleEntity {    
        @Id
        @Column(name = "ID", unique = true, nullable = false)
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;

        @Column(name = "Name", nullable = false)
        private String name;

        @Column(name = "Description")
        private String description;

        @Column(name = "CreatedDate", nullable = false)
        private LocalDateTime createdDate;    
    }

我的仓库:

    public interface ExampleRepository extends CrudRepository<ExampleEntity, Integer> {
    }

我的集成测试配置:

    @Configuration
    @EnableJpaRepositories(
        basePackages = "com.test.example.repository",
        entityManagerFactoryRef = "integrationTestEntityFactory",
        transactionManagerRef = "integrationTestTransactionManager")
    public class IntegrationTestConfig {
        @Bean
        @ConfigurationProperties(prefix = "config.datasource")
        public DataSource integrationTestDatasource() {
            return new EmbeddedDatabaseBuilder()
                .addScript("scripts/schema.sql")
                .build();
        }

        @Bean
        public LocalContainerEntityManagerFactoryBean integrationTestEntityFactory(final DataSource integrationTestDatasource) {

            HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            vendorAdapter.setDatabase(Database.SQL_SERVER);
            vendorAdapter.setShowSql(false);

            LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
            factory.setJpaVendorAdapter(vendorAdapter);
            factory.setPackagesToScan("com.test.example.entity");
            factory.setDataSource(integrationTestDatasource);
            return factory;
        }

        @Bean
        public PlatformTransactionManager integrationTestTransactionManager(final LocalContainerEntityManagerFactoryBean integrationTestEntityFactory) {
            JpaTransactionManager transactionManager = new JpaTransactionManager();
            transactionManager.setEntityManagerFactory(integrationTestEntityFactory.getObject());
            return transactionManager;
        }

        @Bean
        public NamedParameterJdbcTemplate integrationTestJdbcTemplate(final DataSource integrationTestDatasource) {
            return new NamedParameterJdbcTemplate(integrationTestDatasource);
        }
    }

【问题讨论】:

  • 阅读 HSQLDB 的文档,而不是 SQL Server,如果您想了解支持的数据类型:HyperSQL User Guide - Datetime types。没有datetimeoffset这样的数据类型。
  • @Andreas 我已经读过,它没有提到它不支持 SQL Server 的所有功能。当我完成研究但仍需要帮助时,因缺乏研究而投反对票是微不足道且不必要的。如果您建议 HSQLDB 不能做我需要的事情,那么这听起来像是一个答案,不仅可以帮助我,还可以帮助其他人在未来遇到这个问题。
  • 在您的研究中您发现HSQLDB 支持SQL Server 的数据类型 的哪些地方?您提供的链接显示 “HyperSQL 2.4 在 MSS 兼容模式下添加了几个 datetime 函数。其中包括 DATEPART、DATENAME、EOMONTH 以及兼容的 DATEADD 和 DATEDIFF 行为”。职能!!!不是数据类型。 “MS SQLServer 和 Sybase 兼容性”部分根本没有提到列数据类型。
  • @Andreas 听起来你今天过得很糟糕。如果你没有阻止我获得帮助而毁了我的,我将不胜感激。还是这个网站对人们没有帮助?
  • 请注意 HSQLDB 指南没有列出所有兼容模式支持的函数和类型名称,包括这个。 OP 使用的版本比引用的文档旧。

标签: java sql spring-boot spring-data-jpa hsqldb


【解决方案1】:

对于datetimeoffset SQL 类型,您应该使用java.time.OffsetDateTime Java 类型:

    @Column(name = "CreatedDate", nullable = false)
    private OffsetDateTime createdDate; 

这是如果您的类路径中有 2.2 版的 JPA。否则你需要创建一个custom converter

【讨论】:

  • 即使我将字段留在实体之外,我也会收到错误消息。我得到的错误肯定是在 HSQLDB 创建列中,而不是在 JPA 从表中获取数据。
  • 我将致力于创建一个转换器,感谢您的提醒!
  • 我加了转换器,还是有这个问题。
  • 我根据组织中的现有工作使用 LocalDateTime,但 OffsetDateTime 会更好地满足我的需求,并且无需转换器启动。你的回答没有具体回答我的问题,但它仍然是很好的建议。感谢您的帮助!
【解决方案2】:

最新版本的 HSQLDB 在 MSS 兼容模式下支持 DATETIMEOFFSET。使用 2.4.1。

如果您想继续使用不支持此类型的旧版本,请在创建表之前使用CREATE TYPE DATETIMEOFFSET AS TIMESTAMP WITH TIME ZONE

【讨论】:

  • 这解决了我的问题。需要注意的是,虽然 SQL Server 可以在列定义中使用精度输入,但 HSQLDB 不会。这确实意味着我的测试数据不会与生产数据完全匹配,但结合@MaciejKowalski 更改为 OffsetDateTime,我认为这不是问题。
猜你喜欢
  • 1970-01-01
  • 2017-06-14
  • 2015-12-11
  • 1970-01-01
  • 2018-10-03
  • 1970-01-01
  • 2018-05-22
  • 2013-03-06
相关资源
最近更新 更多