gpt4 book ai didi

java - 在 MySQL 中存储为 DATE 的 LocalDate 返回不同的结果

转载 作者:可可西里 更新时间:2023-11-01 08:38:58 25 4
gpt4 key购买 nike

我有一个 Java 类,其字段定义为:

  @Column
@NotNull
private LocalDate availabilityDate;

它映射到定义为的列:

availability_date DATE NOT NULL

当我比较通过 Spring Data 保存到 MySQL 数据库之前和之后的日期时,我在 JUnit 中得到不同的结果:

Expecting:
<[InventoryAvailability(size=000, availabilityDate=2018-02-07, inventoryContextId=3847, quantity=15, lastChange=2018-02-08T14:32:24.770+01:00[Europe/Berlin]),
InventoryAvailability(size=001, availabilityDate=2018-02-07, inventoryContextId=3847, quantity=15, lastChange=2018-02-08T14:32:26.337+01:00[Europe/Berlin])]>
to contain exactly in any order:
<[InventoryAvailability(size=001, availabilityDate=2018-02-08, inventoryContextId=3847, quantity=15, lastChange=2018-02-08T14:32:26.337+01:00[Europe/Berlin]),
InventoryAvailability(size=000, availabilityDate=2018-02-08, inventoryContextId=3847, quantity=15, lastChange=2018-02-08T14:32:24.770+01:00[Europe/Berlin])]>

这怎么可能?我以为只有 TIMESTAMPS 有时区。我正在考虑将其存储为毫秒 LONG 或作为 UTC ZonedDateTime 作为解决方法,但我怀疑我不明白这里的一些重要内容。

最佳答案

我的回答是基于假设您正在使用 java.time.LocalDate 作为您的字段 availabilityDate。我编写了简单的 Spring Boot 应用程序,它使用 Spring Data 和 MySQL 连接器(数据库版本为 5.7.20-log)来重现您的案例。

测试 DateHolderRepositoryTest 失败,因为它不知道如何将 LocalDate 转换为数据库中的 Date。然后我添加了对 hibernate-java8 的依赖,测试变成了绿色(如 https://www.thoughts-on-java.org/hibernate-5-date-and-time/ 中所述)。

所以我的假设是你的 JUnit 测试有问题,或者它可能与你实体的 equals 和 hashCode 方法实现有关(因为 Hamcrest 将在下面使用 equals 来比较类,并且从数据库类加载和创建的类是只是不同的实例,默认的 Object equals 方法将返回 false)。您问题中的 availabilityDate=2018-02-08 显示没有时区的日期。

为了重现我的结果,我添加了测试应用程序的代码。我这是我的 DateHolder 类,它包含 id 和 availabilityDate,并包含基于字段 id 的 hashCode 和 equals 实现:

package hello;

import java.time.LocalDate;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;

@Entity
public class DateHolder {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;

@Column
@NotNull
private LocalDate availabilityDate;

protected DateHolder() {}

public DateHolder(LocalDate availabilityDate)
{
this.availabilityDate = availabilityDate;
}

@Override
public String toString()
{
return String.format("DateHolder[id=%d, availabilityDate='%s']", id, availabilityDate);
}

public Integer getId()
{
return id;
}

public LocalDate getAvailabilityDate()
{
return availabilityDate;
}

@Override
public int hashCode()
{
return id;
}

@Override
public boolean equals(Object other)
{
if (other instanceof DateHolder)
{
return this.id == ((DateHolder)other).id;
}
else
{
return false;
}
}
}

这是我的 JPA 存储库:

package hello;
import org.springframework.data.repository.CrudRepository;

public interface DateHolderRepository extends CrudRepository<DateHolder, Long>
{
}

这是主要的 Spring Boot 应用程序类:

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
public static void main(String[] args)
{
SpringApplication.run(Application.class);
}
}

这是测试,它创建了 2 个 DateHolder,将它们保存在数据库中,并将它们与数据库中的任何内容进行比较(它不考虑顺序)。它还测试从数据库加载的第一个实体的 toString() 方法的返回值。

package hello;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;

import java.time.LocalDate;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class DateHolderRepositoryTest
{
@Autowired
private DateHolderRepository repository;

@Test
public void testFindByLastName()
{
DateHolder dateHolder1 = new DateHolder(LocalDate.parse("2018-02-07"));
DateHolder dateHolder2 = new DateHolder(LocalDate.parse("2018-02-08"));

repository.save(dateHolder1);
repository.save(dateHolder2);

Iterable<DateHolder> dateHolders = repository.findAll();
assertThat(dateHolders, containsInAnyOrder(dateHolder2, dateHolder1));

assertThat(dateHolders.iterator().next().toString(), is("DateHolder[id=1, availabilityDate='2018-02-07']"));
}
}

关于java - 在 MySQL 中存储为 DATE 的 LocalDate 返回不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48686911/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com