14

使用 JPA CriteriaBuilder API将LocalDate字段(例如“2017-09-27”)保存到 mySQLDate列时,结果不同(例如“2017-09-26”)。

我已经验证我的数据库的时区设置为 UTC,SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP)因为结果是 '00:00:00'。

我在本地对此进行测试,并且我的时区为 GMT + 2,所以我怀疑当从LocalDate​​to发生转换时,Date将扣除 2 小时并在请求日期前 1 天生成一个日期(假设该LocalDate字段为由于没有时间信息,因此被视为 00:00:00。

在这种情况下保存 LocalDates 的最佳方法是什么?我是否应该遵循此处的建议https://stackoverflow.com/a/29751575/3832047并将所有 LocalDate 字段明确设置为 UTC 或类似的东西?

我进行了测试,看看在代码中转换它们时会发生什么,并得到以下结果:

Date convertedDate = Date.valueOf(localDate);

转换结果

编辑

这是我用来检索数据的代码示例,其中也发生了奇数日期更改。如果我请求 的数据2017-06-27,我会收到 的结果2017-06-26

CriteriaBuilder criteriaBuilder = sessionFactory.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(HorseAndTrailerRequest.class);
Root<HorseAndTrailerRequest> criteria = criteriaQuery.from(HorseAndTrailerRequest.class);

ParameterExpression<LocalDate> effectiveDateParameter = criteriaBuilder.parameter(LocalDate.class);
    criteriaQuery.select(criteria)
            .where(
                    criteriaBuilder.equal(criteria.get("effectiveDate"), effectiveDateParameter)
            );

TypedQuery<HorseAndTrailerRequest> query = sessionFactory.getCurrentSession().createQuery(criteriaQuery);
query.setParameter(effectiveDateParameter, date);
return query.getResultList();
4

2 回答 2

2

由于LocalDate没有 TimeZone,您可以在数据库模式中将 column_date 映射为 long,并使用AttributeConverterto 转换LocalDate为 long 以避免时区转换问题:

import javax.persistence.Converter;
import java.time.LocalDate;
import javax.persistence.AttributeConverter;
@Converter
public class LocalDateToLong implements AttributeConverter<LocalDate, Long> {

    @Override
    public Long convertToDatabaseColumn(LocalDate date) {
        if (date != null) {
            long epochDay = date.toEpochDay();
            return epochDay;
        }
        return null;
    }

    @Override
    public LocalDate convertToEntityAttribute(Long epochDay) {
        // TODO Auto-generated method stub
        if (epochDay != null) {
            LocalDate date = LocalDate.ofEpochDay(epochDay);
            return date;
        }
        return null;
    }

}
于 2017-09-28T09:44:09.400 回答
1

我有同样的问题,我解决了它看到休眠 atlassian 问题(这里是线程:https ://hibernate.atlassian.net/browse/HHH-11396 )。您有两种选择:

  1. -Duser.timezone=Europe/Berlin使用或以编程方式设置 JVMTimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));

  2. 创建一个分区的 DateTime,然后将其转换回 Date

    public static final ZoneId ZONE_EUROPE_BERLIN = ZoneId.of("Europe/Berlin");
    
    @Override
    public Date convertToDatabaseColumn(LocalDate locDate) {
        if (locDate == null) {
            return null;
        }
    
        ZonedDateTime zonedDateTime = locDate.atStartOfDay(ZONE_EUROPE_BERLIN);
        LocalDate producerLocalDate = zonedDateTime.toLocalDate();
        Date date = Date.valueOf(producerLocalDate);
    
        return date;
    }
    

我使用了第二种选择。

于 2019-07-08T17:12:01.463 回答