Сохранение объекта с полем DateTime в базе данных objectdb

Я хочу сохранить экземпляр моего класса в objectdb.

@Entity
public class MyClazz {
  @Column(nullable = false)
  DateTime date;
}

В спящем режиме мне просто нужно аннотировать поле дополнительной аннотацией.

@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")

Но поскольку я хочу использовать objectdb, я не могу использовать эту аннотацию, поэтому получаю исключение («Попытка сохранить экземпляр не сохраняемого типа org.joda.time.DateTime»)

Проблема в том, что objectdb отключает «поддержку» для сериализуемых типов. (см. здесь) Я почти уверен, что они делают это для веская причина, поэтому хочу сохранить это таким образом.

В качестве обходного пути на данный момент я использую хук pre и post.

@Column(nullable = false)   
private Date date = new Date();

@Transient
private DateTime dateTime;

@PrePersist
private void persist() {
    date = dateTime.toDate();
}

@PostLoad
private void load() {
    dateTime = new DateTime(date.getTime());
}

Мой вопрос: есть ли другой способ? Я хочу избавиться от дополнительного поля даты.


person Marcel Jaeschke    schedule 28.07.2013    source источник
comment
Таким образом, дата, которую вы сохраняете, зависит от часового пояса по умолчанию на машине, на которой работает jvm? Однажды системный администратор изменил часовой пояс, и вы начали получать события в прошлом...   -  person Nikola Yovchev    schedule 30.07.2013
comment
Я уже говорил вам, что это просто быстрый пример кода, не продуктивный код. Да, j.u.Date неправильный кандидат, но ради вопроса: ему все равно. Поэтому, пожалуйста, перестаньте придираться ко мне за вещи, которые не относятся к вопросу.   -  person Marcel Jaeschke    schedule 31.07.2013


Ответы (2)


Я почти уверен, что они делают это по уважительной причине, поэтому хочу, чтобы так и оставалось.

Да. Когда вы сохраняете сериализованный объект в базе данных, ваши запросы не смогут выполнять какие-либо тесты на объекте; например проверить, является ли одна дата более поздней, чем другая. Кроме того, вы делаете ваше приложение уязвимым для проблемы несовместимых серийных версий. (Вероятно, это не проблема в этом конкретном примере, но проблема неоднократно возникает в вопросах SO...)

Мой вопрос: есть ли другой способ? Я хотел бы избавиться от дополнительного поля даты.

К сожалению, я не думаю, что есть.

person Stephen C    schedule 28.07.2013

В Joda DateTime — это момент, так же как Java API Date — это момент. Основное различие между ними заключается в том, что Date не является неизменным.

Поскольку оба типа являются обертками для длинного целого числа, представляющего количество миллисекунд, прошедших с 1 января 1970 года по всемирному координированному времени, одной из альтернатив для вас является просто не сохранять DateTime вообще, а вместо этого просто сохранять длинное целое число, которое оно обертывает.

Вот выдержка из Joda Javadoc:

Внутри класс содержит две части данных. Во-первых, он хранит дату и время в миллисекундах из эпохи Java 1970-01-01T00:00:00Z. Во-вторых, он содержит хронологию, которая определяет, как мгновенное значение миллисекунды преобразуется в поля даты и времени. Хронологией по умолчанию является ISOChronology, которая является согласованным международным стандартом и совместима с современным григорианским календарем.

Пока хронология, используемая вашим приложением, постоянна или всегда известна, вы можете легко восстановить DateTime из длинного целочисленного поля с помощью:

DateTime dt = new DateTime(longInstantFieldInMillis, myChronology);
person scottb    schedule 28.07.2013
comment
Как это относится к Вопросу? - person Stephen C; 28.07.2013
comment
@StephenC: Как это не так? Он спросил, как сохранить DateTime, я предложил альтернативу. - person scottb; 28.07.2013
comment
Нет. Он попросил способ сохранить DataTime без дополнительного поля. Он хочет избавиться от этого дополнительного поля. - person Stephen C; 28.07.2013
comment
Сохранять временную метку (длинную) тоже было одной из моих первых идей. Но я хочу использовать объектно-ориентированную базу данных. Поэтому для меня нет смысла, когда я скрываю информацию (дату) примитивным полем. - person Marcel Jaeschke; 28.07.2013
comment
@StephenC: Ну, ну ... он может избавиться от дополнительного поля даты, сохранив момент как длинное целое число вместо DateTime. По общему признанию, это решение требует изменения модели данных, что может быть неосуществимо, например. если база данных уже очень большая. Моя предвзятость всегда состоит в том, чтобы сохранять мгновения как примитивы. Сохранение DateTime может привести к сохранению одного и того же объекта Chronology в базе данных тысячи или сотни тысяч раз. Если хронология всегда известна или постоянна, эта избыточность не требуется. - person scottb; 28.07.2013
comment
@MarcelJaeschke: Да, я понимаю. Объекты Date и DateTime представляют собой такие тонкие оболочки, что я в любом случае склонен думать о них как о длинных целых числах. Но я вижу вашу точку зрения. - person scottb; 28.07.2013
comment
@scottb: Просто хочу добавить, что я предпочитаю Date длинному, потому что я могу видеть дату как дату в проводнике objectdb. Кроме того, мое/наше руководство по стилю говорит, что DateTime следует использовать для дат. - person Marcel Jaeschke; 28.07.2013
comment
@MarcelJaeschke Довольно часто в БД хранятся только временные метки, потому что это экономит место, экономит на ошибках и не позволяет администраторам БД изменять даты с помощью странных запросов и вместо этого заставляет их использовать внешний интерфейс. Использование даты и времени только потому, что ваш dbexplorer может ее прочитать, - это шутка. - person Nikola Yovchev; 29.07.2013
comment
@baba Как эффективно сохранить информацию, зависит от DBS, а не от пользователя. Если DB-Schema влияет на API, значит, что-то идет не так. Как сказал Скоттб; DateTime в основном представляет собой оболочку для числового значения. Но вдобавок он доводит до пользователя логику даты. Поэтому я думаю, что умные oodbs просто сохраняют числовое значение. Кстати: Сказать, что семантическая контекстуальная информация — это шутка, для меня это шутка. - person Marcel Jaeschke; 29.07.2013
comment
Говоря об эффективности, мне интересно, какой размер больше: длинный или сериализованная дата/строка... Кроме того, контекстная информация о дате не нужна. Временная метка — это ВСЕ, что необходимо для уникальной идентификации даты, без контекста или чего-либо еще. Кроме того, нет шансов на загрязнение записей при работе в кластерной среде или изменении локали... Так много причин против использования даты и времени... Единственная причина использовать дату и время - быть читаемым на уровне БД, что, конечно, шутка, поскольку, если ваше приложение требует, чтобы ваш администратор базы данных читал данные и выполнял специальные запросы, вы все испортили. - person Nikola Yovchev; 29.07.2013
comment
@baba Ты не понимаешь. Никто не говорит о хранении даты в сверхбольшой структуре данных. Если класс даты (API) хорошо спроектирован, ему потребуется только длинная (временная метка) для сохранения даты. (Кстати: отметка времени подведет вас, если вам нужен часовой пояс). - person Marcel Jaeschke; 30.07.2013
comment
И потому что ты все еще думаешь, что это шутка. Чтобы иметь контекстную информацию, такую ​​​​как «эй, это долго», следует интерпретировать как дату и время, если вам нужно использовать существующий db-explorer вместо разработки собственного. Я не могу мысленно преобразовать длинное в дату. Ты?! - person Marcel Jaeschke; 30.07.2013
comment
@MarcelJaeschke Метки времени ДОСТАТОЧНО, чтобы определить, КОГДА что-то произошло. Не имеет смысла хранить часовой пояс. Отметка времени 1375185600000 означает 2 часа (GMT+2) сегодня. Это также означает 3 часа по Гринвичу +3. Но все же той же временной метки достаточно, чтобы однозначно определить, КОГДА что-то произошло. Кроме того, нет никаких причин проектировать вашу базу данных вокруг того, чтобы ее было ЛЕГКО ИССЛЕДОВАТЬ С ПОТРЯСАЮЩЕЙ БД ИССЛЕДОВАТЕЛЬ! Вы должны спроектировать свою базу данных так, чтобы она была эффективной и устраняла двусмысленность. И да, я могу преобразовать длинное в дату, но мое превосходство в математике вряд ли имеет значение. - person Nikola Yovchev; 30.07.2013
comment
@baba Прости, что ты снова меня неправильно понял. Я сказал, что если вам нужна информация о часовом поясе, вы потерпите неудачу с отметкой времени. Пример: вы хотите запросить все сообщения SO, которые были отправлены пользователем во второй половине дня (время пользователя). Если вы просто храните метку времени (UTC), вы не можете этого сделать. И нет причин зазнаваться и кричать на меня. - person Marcel Jaeschke; 30.07.2013
comment
@MarcelJaeschke, как узнать, в каком часовом поясе был пользователь? Вы бы получить его системное время? Вы бы использовали фрагмент javascript, чтобы определить часовой пояс пользователя и отправить его обратно на ваш сервер? Вы бы сделали это для каждого события? Мне кажется, что это пустая трата полосы пропускания. Вам лучше определить ip/часовой пояс пользователя во время входа в систему и больше не отправлять. Посмотрите, как устроены большие системы. Они не хранят часовой пояс для событий, потому что его можно вывести по другим данным: например, IP-адресу пользователя или даже часовому поясу, полученному от пользователя при входе в систему. Но вы не сохраняете его для каждого события. - person Nikola Yovchev; 30.07.2013
comment
Я почти не понимаю, зачем мне сохранять что-то большее, чем отметка времени в моей базе данных. Подумайте о преимуществах отказа от ее хранения: экономия места, независимость от языкового стандарта сервера, отпугивание людей от выполнения специальных запросов для исправления ошибочных данных и возможность форматирования даты на стороне клиента. Кроме того, нет способа определить часовой пояс пользователя, если только вы не готовы тратить пропускную способность на его передачу. Если вы делаете школьный проект, вы можете не возражать против всех этих минусов, но если мы говорим о реальных случаях, решение, сохраняющее часовой пояс, также просто неправильно. - person Nikola Yovchev; 30.07.2013
comment
@baba Если вы проверите мой профиль, вы увидите имя моего работодателя и то, что я давно не учусь в школе. И поверьте мне, у меня есть несколько лет опыта в этом бизнесе. Может быть, поэтому я бы никогда не сказал, что информация о часовом поясе вообще не нужна. Это зависит от ваших требований. Если бы вы работали на меня или над этим проектом, вы бы увидели, что информация о часовом поясе не совсем бесполезна. Кроме того. Кто сказал, что требования никогда не изменятся?! На самом деле сделают! Хм... мы уже давно не по теме. Так что хорошего дня. - person Marcel Jaeschke; 30.07.2013
comment
И еще: в наши дни не все работают над веб-приложениями. Существует еще множество невидимых сервисов и встроенных систем. Так что возможно клиент сам определяет время. - person Marcel Jaeschke; 30.07.2013
comment
Пожалуйста, осветите меня примером ситуации, когда часовой пояс имеет значение и как вы его собираете. - person Nikola Yovchev; 30.07.2013
comment
Кроме того, в предоставленном коде вы используете сервер/машину, в которой jvm работает в часовом поясе по умолчанию, а не в часовом поясе пользователя. Это означало бы, что в вашей компании вам нравится хранить ошибочные данные. - person Nikola Yovchev; 30.07.2013
comment
Я не могу рассказать вам подробности, потому что это конфиденциально. Но предположим, вы получаете сообщения об автомобильных авариях со всего мира. С датой и часовым поясом вы можете узнать, что 60% всех аварий происходят до 8 утра. Ваш второй момент: вы правы, метод загрузки неверен. Но это просто быстрый пример. Нет продуктивного кода, который прошел бы наши тесты. Поэтому я могу заверить вас, что наши данные не ошибочны. - person Marcel Jaeschke; 31.07.2013