Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Liquibase配置持久化LocalDate时,Spring引导存储库返回错误的值_Java_Jpa_Spring Boot_Timezone_Liquibase - Fatal编程技术网

Java 使用Liquibase配置持久化LocalDate时,Spring引导存储库返回错误的值

Java 使用Liquibase配置持久化LocalDate时,Spring引导存储库返回错误的值,java,jpa,spring-boot,timezone,liquibase,Java,Jpa,Spring Boot,Timezone,Liquibase,我有一个小弹簧靴项目;应用程序所做的只是持久化一个带有LocalDate和LocalDateTime的简单实体。为了确保不同时区的应用服务器之间的日期格式一致,我在启动后将默认Java时区设置为UTC 我有一组集成测试(使用内存中的H2数据库),它们将实体保存到数据库中,检索实体,并进行检查以确保没有任何属性发生变化。当这些测试依靠Hibernate使用@Entity内省创建模式时,测试通过。但是,当我在类路径上包括Liquibase并指向有效的配置文件时,测试在日期值的相等断言上失败,持久化的

我有一个小弹簧靴项目;应用程序所做的只是持久化一个带有LocalDate和LocalDateTime的简单实体。为了确保不同时区的应用服务器之间的日期格式一致,我在启动后将默认Java时区设置为UTC

我有一组集成测试(使用内存中的H2数据库),它们将实体保存到数据库中,检索实体,并进行检查以确保没有任何属性发生变化。当这些测试依靠Hibernate使用@Entity内省创建模式时,测试通过。但是,当我在类路径上包括Liquibase并指向有效的配置文件时,测试在日期值的相等断言上失败,持久化的LocalDate值始终返回为未保存实体的值的前一天

根据我到目前为止的观察,我猜测在我的
@PostConstruct
方法有机会更改默认时区之前,Liquibase会进行某种初始化并基于Java环境设置时间偏移。如果是这样,如何正确配置Liquibase以在初始化后拾取正确的时区?为什么LocalDate不受LocalDateTime的影响?为什么它总是给我前一天的日期,而不是根据我的初始时区设置更容易预测

相关类别、配置和结果如下所示。感谢所有能帮我解开这一切的人

DatePersistenceApplication.java:

@SpringBootApplication
public class DatePersistenceApplication {

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

    public DatePersistenceApplication() {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }
}
DatePersistenceEntity.java:

@Entity
public class DatePersistenceEntity {

    @Id private UUID id = UUID.randomUUID();
    @Column private LocalDate localDate;
    @Column private LocalDateTime localDateTime;

    public UUID getId() {
        return id;
    }

    public LocalDate getLocalDate() {
        return localDate;
    }

    public void setLocalDate(LocalDate localDate) {
        this.localDate = localDate;
    }

    public LocalDateTime getLocalDateTime() {
        return localDateTime;
    }

    public void setLocalDateTime(LocalDateTime localDateTime) {
        this.localDateTime = localDateTime;
    }
}
DatePersistenceRepository.java:

public interface DatePersistenceRepository extends PagingAndSortingRepository<DatePersistenceEntity, UUID> { }
application.properties:

spring.liquibase.change-log = classpath:db/liquibase-changelog.xml
liquibase-changelog.xml:

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">

    <changeSet author="example" id="create-date-persistence-entity">
        <createTable tableName="date_persistence_entity">
            <column name="id" type="UUID">
                <constraints nullable="false"/>
            </column>
            <column name="local_date_time" type="TIMESTAMP">
                <constraints nullable="false"/>
            </column>
            <column name="local_date" type="TIMESTAMP">
                <constraints nullable="false"/>
            </column>
        </createTable>
        <addPrimaryKey columnNames="id" constraintName="date_entity_pk" tableName="date_persistence_entity"/>
    </changeSet>

</databaseChangeLog>
注:

  • 我的测试正在PST时区运行。基于一些有限的实验,一天中的时间似乎不会影响测试结果
  • 如果我在
    @PostConstruct
    方法中删除
    Timezone.setDefaullt(…)
    调用,或者将
    -Duser.Timezone=UTC作为JVM参数传入,则两个测试都会通过
  • 如果我使用HSQL而不是H2作为后台数据库运行测试,那么这两个测试都会通过
  • 如果我通过从类路径中删除依赖项来禁用Liquibase集成,那么两个测试都会通过
  • 在application.properties中添加
    spring.jpa.properties.spring.hibernate.jdbc.time_zone=UTC
    属性无效

当您仅使用hibernate而不使用liquibase时,
LocalDate
的数据类型是如何创建的?我想问题在于
LocalDate
的类型。我认为JDBC驱动程序所做的是将日期减到2018-02-06:00:00:00(或01,不知道),然后当您加载带有时区的
LocalDate
时,它会改变。尝试将local_date更改为date,然后执行测试。禁用Liquibase并登录SQL后,应用程序在启动时打印以下内容:
Hibernate:create table date_persistence_entity(id binary not null,local_date date,local_date_time timestamp,primary key(id))
。但是,将liquibase配置更改为使用
date
type不会对测试结果产生影响。
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">

    <changeSet author="example" id="create-date-persistence-entity">
        <createTable tableName="date_persistence_entity">
            <column name="id" type="UUID">
                <constraints nullable="false"/>
            </column>
            <column name="local_date_time" type="TIMESTAMP">
                <constraints nullable="false"/>
            </column>
            <column name="local_date" type="TIMESTAMP">
                <constraints nullable="false"/>
            </column>
        </createTable>
        <addPrimaryKey columnNames="id" constraintName="date_entity_pk" tableName="date_persistence_entity"/>
    </changeSet>

</databaseChangeLog>
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR]   DatePersistenceApplicationTests.datePreservedDuringSave:33 LocalDate was transformed during persistence expected:<2018-02-06> but was:<2018-02-05>
[INFO]
[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0