Как сохранить дату/время и метки времени в часовом поясе UTC с JPA и Быть в спящем режиме

Извлеките годовую комиссию в вашем запросе и используйте ее в запросе-обертке для сортировки результатов:

select employee, commission
from (
    select 
        employee, 
        json_agg (json_build_object('period', period, 'commission', commission)) as commission,
        max(case period when '1Y' then commission end) as one_year_commission
    from table_name 
    group by employee
    ) s
order by one_year_commission
95
задан Vlad Mihalcea 11 May 2017 в 13:05
поделиться

5 ответов

Насколько я знаю необходимо поместить все приложение Java в часовой пояс UTC (так, чтобы Были в спящем режиме, сохранит даты в UTC), и необходимо будет преобразовать в любой часовой пояс, желаемый при отображении материала (по крайней мере, мы делаем это этот путь).

При запуске, мы делаем:

TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));

И набор желаемый часовой пояс к DateFormat:

fmt.setTimeZone(TimeZone.getTimeZone("Europe/Budapest"))
49
ответ дан approxiblue 24 November 2019 в 05:49
поделиться

Вы думали бы, что эта типичная проблема будет заботиться о, в спящем режиме. Но нет! Существует несколько "взломов" для разбираний в нем.

тот, который я использую, должен сохранить Дату как Длинное в базе данных. Таким образом, я всегда работаю с миллисекундами после 01.01.70. У меня затем есть методы считывания и методы set на моем Классе, которые возвращаются/принимают только Даты. Таким образом, API остается тем же. Вниз сторона - то, что у меня есть longs в базе данных. ТАКИМ ОБРАЗОМ с SQL я могу в значительной степени только сделать <>, = сравнения - не представляют себе операторы даты.

Другой подход является пользователю пользовательским типом отображения, как описано здесь: http://www.hibernate.org/100.html

я думаю, что корректный способ иметь дело с этим состоит в том, чтобы использовать Календарь вместо Даты все же. С Календарем можно установить TimeZone перед сохранением.

ПРИМЕЧАНИЕ: Глупый stackoverflow не позволит мне прокомментировать, таким образом, вот будет ответ на david a.

, Если Вы создаете этот объект в Чикаго:

new Date(0);

В спящем режиме, сохраняет его как "31.12.1969 18:00:00". Даты должны быть лишены часового пояса, таким образом, я не уверен, почему корректировка была бы внесена.

10
ответ дан codefinger 24 November 2019 в 05:49
поделиться

Дата не находится ни в каком часовом поясе (это - офис миллисекунды с определенного момента вовремя то же для всех), но лежащий в основе (R) DBS обычно хранят метки времени в политическом формате (год, месяц, день, час, минута, во-вторых...), который является чувствительным часовым поясом.

Чтобы быть серьезными, Будьте в спящем режиме, ДОЛЖЕН быть, позволяют быть сказанным в некоторой форме об отображении, что дата DB находится в таком-то и таком-то часовом поясе так, чтобы, когда это загружает или хранит его, это не принимало свое собственное...

2
ответ дан 24 November 2019 в 05:49
поделиться

Пожалуйста, ознакомьтесь с моим проектом на Sourceforge, в котором есть типы пользователей для стандартных типов даты и времени SQL, а также JSR 310 и Joda Time. Все типы пытаются решить проблему компенсации. См. http://sourceforge.net/projects/usertype/

РЕДАКТИРОВАТЬ: В ответ на вопрос Дерека Махара, приложенный к этому комментарию:

«Крис, ваши типы пользователей работают с Hibernate 3 или выше? - Дерек Махар, 7 ноября 2010 г., 12:30 "

Да, эти типы поддерживают версии Hibernate 3.x, включая Hibernate 3.6.

3
ответ дан 24 November 2019 в 05:49
поделиться

Hibernate игнорирует данные о часовых поясах в Dates (потому что их нет), но на самом деле проблемы возникают из-за уровня JDBC. ResultSet.getTimestamp и PreparedStatement.setTimestamp оба говорят в своих документах, что они по умолчанию преобразуют даты в / из текущего часового пояса JVM при чтении и записи из / в базу данных.

Я нашел решение этой проблемы в Hibernate 3.5, создав подкласс org.hibernate.type.TimestampType , который заставляет эти методы JDBC использовать UTC вместо местного часового пояса:

public class UtcTimestampType extends TimestampType {

    private static final long serialVersionUID = 8088663383676984635L;

    private static final TimeZone UTC = TimeZone.getTimeZone("UTC");

    @Override
    public Object get(ResultSet rs, String name) throws SQLException {
        return rs.getTimestamp(name, Calendar.getInstance(UTC));
    }

    @Override
    public void set(PreparedStatement st, Object value, int index) throws SQLException {
        Timestamp ts;
        if(value instanceof Timestamp) {
            ts = (Timestamp) value;
        } else {
            ts = new Timestamp(((java.util.Date) value).getTime());
        }
        st.setTimestamp(index, ts, Calendar.getInstance(UTC));
    }
}

То же самое необходимо сделать, чтобы исправить TimeType и DateType, если вы используете эти типы. Обратной стороной является то, что вам придется вручную указать, что эти типы должны использоваться вместо значений по умолчанию в каждом поле даты в ваших POJO (а также нарушает чистую совместимость с JPA), если кто-то не знает более общего метода переопределения.

ОБНОВЛЕНИЕ: Hibernate 3.6 изменил API типов. В версии 3.6 я написал класс UtcTimestampTypeDescriptor для реализации этого.

public class UtcTimestampTypeDescriptor extends TimestampTypeDescriptor {
    public static final UtcTimestampTypeDescriptor INSTANCE = new UtcTimestampTypeDescriptor();

    private static final TimeZone UTC = TimeZone.getTimeZone("UTC");

    public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
        return new BasicBinder<X>( javaTypeDescriptor, this ) {
            @Override
            protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
                st.setTimestamp( index, javaTypeDescriptor.unwrap( value, Timestamp.class, options ), Calendar.getInstance(UTC) );
            }
        };
    }

    public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
        return new BasicExtractor<X>( javaTypeDescriptor, this ) {
            @Override
            protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
                return javaTypeDescriptor.wrap( rs.getTimestamp( name, Calendar.getInstance(UTC) ), options );
            }
        };
    }
}

Теперь, когда приложение запускается, если вы установите для TimestampTypeDescriptor.INSTANCE экземпляр UtcTimestampTypeDescriptor, все временные метки будут сохраняться и обрабатываться как находящиеся в формате UTC без необходимости изменения аннотаций в POJO. [Я еще не тестировал это]

42
ответ дан 24 November 2019 в 05:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: