Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> История Entity 
V
    Опции темы
ShurikA
Дата 6.1.2009, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Мне нужно сохранять историю изменений Entities в таблицу истории.
Пытаюсь сделать это через EntityListener - @PreUpdate, вроде по логике должно быть именно так.
Но, дело в том что из нутри Entity нету инджекшен @PersistanceContext.
Какое правильное решение для такого дела?


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
powerOn
Дата 6.1.2009, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 28
Всего: 159



Цитата(ShurikA @  6.1.2009,  12:39 Найти цитируемый пост)
Мне нужно сохранять историю изменений Entities в таблицу истории.
Пытаюсь сделать это через EntityListener - @PreUpdate, вроде по логике должно быть именно так.
Но, дело в том что из нутри Entity нету инджекшен @PersistanceContext.
Какое правильное решение для такого дела? 


Для ведения истории обычно entity имеет поле для версии и из БД их просто не удаляют.



--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ShurikA
Дата 6.1.2009, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Цитата(powerOn @  6.1.2009,  12:35 Найти цитируемый пост)
Для ведения истории обычно entity имеет поле для версии и из БД их просто не удаляют.

Я уже думал об этом, но нужно именно копировать в другую таблицу.

Добавлено через 2 минуты и 2 секунды
powerOn
Кстати, а если сделать так как ты сказал. То каким образом задавать EntityManager-у условие подбора правильного Entity?

Добавлено через 3 минуты и 1 секунду
Цитата(powerOn @  6.1.2009,  12:35 Найти цитируемый пост)
Для ведения истории обычно entity имеет поле для версии и из БД их просто не удаляют.

И ещё: как бы это ни было, мне нужен @PersistanceContext.


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
powerOn
Дата 6.1.2009, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 28
Всего: 159



Цитата(ShurikA @  6.1.2009,  13:45 Найти цитируемый пост)
То каким образом задавать EntityManager-у условие подбора правильного Entity?


Через запрос в котором так же будет указана версия объекта. Вообще тут нужно конкретный use case рассмотреть. Возможно, какое-нибудь вообще другое решение подойдет... 

Цитата(ShurikA @  6.1.2009,  13:45 Найти цитируемый пост)
И ещё: как бы это ни было, мне нужен @PersistanceContext. 

В Entity классе его автоматически не получить, поскольку они не управляются контейнером. Эти объекты ты создаешь сам, в отличии от EJB, которые для тебя создал и проинициализировал контейнер EJB. Вот контейнер создавая EJB позаботился о том, чтоб ссылка на EntityManager была поставленна корректно, а ты создавая свои entity нет. ;-) 
Получается что выход тут один (вернее два): 
1) самостоятельно передавать ссылку на EntityManager в слушателя сущностей. Замечу, что разметить аннотациями @PreUpdate и др. можно не только саму сущность, но и другой класс, подключив его в последствии к сущности как слушателя через аннотацию @EntityListeners.
2) Сделать так что бы слушатель сущностей сам находил подходящего EntityManager-а. Например через JNDI lookup.




--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ShurikA
Дата 6.1.2009, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Цитата(powerOn @  6.1.2009,  13:15 Найти цитируемый пост)
Замечу, что разметить аннотациями @PreUpdate и др. можно не только саму сущность, но и другой класс, подключив его в последствии к сущности как слушателя через аннотацию @EntityListeners.

А это интересно... Может ли быть EJB слушателем?


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
powerOn
Дата 6.1.2009, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 28
Всего: 159



Цитата(ShurikA @  6.1.2009,  14:22 Найти цитируемый пост)
Может ли быть EJB слушателем? 

Как простой класс может, но его создавать будет не контейнер EJB, а значит и инжектировать EntityManager не получится... Оно и понятно, ведь в JavaSE приложениях тоже можно использовать JPA и создавать @EntityListeners, а там то не никакого EJB контейнера, все на плечи JPA имплементации положено...


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
MisterCleric
Дата 6.1.2009, 14:47 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1043
Регистрация: 16.2.2006
Где: Харьков, Украина

Репутация: 33
Всего: 38



Господа, может я и не по теме, но согласно пожеланиям автора темы такую задачу можно решить еще и таким простым способом:
повесить в базе триггер на апдейт основной таблицы и ложить в другую таблицу копию измененной записи.
А все остальное, соответственно, согласно логики приложения. Может триггеры и не помогут...


--------------------
ПРИШЕЛ, УВИДЕЛ - ПЕРЕПИСАЛ...
PM MAIL ICQ   Вверх
ShurikA
Дата 7.1.2009, 03:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



У меня такая  идея:
Сделать Message Driven Bean который всего лиш будет принимать обьект Entity, причём не важно какой, и загонять его в базу.
При этом, сам Entity, которому нужна история, будет создавать копию исторического Entity для самого себя, и отправлять в Bean.

Добавлено через 1 минуту и 13 секунд
Цитата(ShurikA @  6.1.2009,  12:45 Найти цитируемый пост)
powerOn, 
Кстати, а если сделать так как ты сказал. То каким образом задавать EntityManager-у условие подбора правильного Entity?

Есть что то такое?


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
ShurikA
Дата 7.1.2009, 10:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Цитата(powerOn @  6.1.2009,  12:35 Найти цитируемый пост)
Для ведения истории обычно entity имеет поле для версии и из БД их просто не удаляют.

Всё таки всё перекрутил и решол делать как ты предложил.
Получилось следующее:
Код

public class CustomerTypeId implements Serializable {

    private Integer id;
    private Date effectiveDate;

    public CustomerTypeId() {
    }

    public CustomerTypeId(Integer id, Date effectiveDate) {
        this.id = id;
        this.effectiveDate = effectiveDate;
    }

    public Integer getId() {
        return this.id;
    }

    public Date getEffectiveDate() {
        return this.effectiveDate;
    }

    @Override
    public boolean equals(Object obj) {
        return ((obj instanceof CustomerTypeId) && 
                ((CustomerTypeId) obj).getId().equals(this.id) &&
                ((CustomerTypeId) obj).getEffectiveDate().equals(this.effectiveDate));
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 97 * hash + (this.id != null ? this.id.hashCode() : 0);
        hash = 97 * hash + (this.effectiveDate != null ? this.effectiveDate.hashCode() : 0);
        return hash;
    }
}

Код

@Stateless
public class CustomerTypeBean implements CustomerTypeRemote {
    @PersistenceContext(unitName="CRM-ejbPU")
    EntityManager em;
    @Resource
    SessionContext ctx;

    /**
     * Creates new customer type
     * @param type
     */
    public void createCustomerType(String type) {
        CustomerType typeObj = new CustomerType();
        typeObj.setType(type);
        typeObj.setOperator(ctx.getCallerPrincipal().getName());
        em.persist(typeObj);
    }
    /**
     * Gets a full list of available customer types
     */
    public List<CustomerType> getAllCustomerTypes() {
        List<CustomerType> availableCustomerTypes = em.createNamedQuery("CustomerType.findAll").getResultList();
        return availableCustomerTypes;
    }
    /**
     * Updates specific Customer type
     * @param id
     * @param newTypeValue
     */
    public void updateCustomerType(int id, String newTypeValue) {
        //find the type first
        CustomerType typeObj = em.find(CustomerType.class, new CustomerTypeId(id, new Date()));
        if(typeObj != null){
            //update
            typeObj.setType(newTypeValue);
        }
    }
}


но сразу появились пару вопросов:
1. В моём случае я не могу пользоваться точьной датой. Так что получается что вот это
Код

 em.find(CustomerType.class, new CustomerTypeId(id, new Date()));

не сработает.
2. Каким образом мапается этот Entity к Customer::type?

На первый вопрос я вроде как могу ответить сказав что так как персистер пользуется методом equals(Object obj)  что бы найти подходящий ключ, то это метод можно просто изменить так как нам нужно (дата должна быть не равна а между effective и expiration) и спокойно пользоваться em.find(CustomerType.class, new CustomerTypeId(id, new Date()));. Исправь если я не прав.

А вот на тему второго у меня даже догадок никаких.


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
powerOn
Дата 7.1.2009, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 28
Всего: 159



Что-то я плохо вопросы понял... Что сделать-то хочешь? Составной ключ (из числа и даты) и поиск по нему?

Цитата(ShurikA @  7.1.2009,  10:11 Найти цитируемый пост)
2. Каким образом мапается этот Entity к Customer::type?


Если Customer::type это как раз и есть составной ключ, то обычно его сущностью мапят с помощью @IdClass аннотации. 




--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ShurikA
Дата 7.1.2009, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



powerOn

Дело не в этом.
Когда составной ключь это 2 цифры которые должны совпадать, то всё понятно.
В моём случае:
id - должен совпадать, а дата должна быть >= effectiveDate.

Это сообщение отредактировал(а) ShurikA - 7.1.2009, 21:19


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
powerOn
Дата 7.1.2009, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 28
Всего: 159



Цитата(ShurikA @  7.1.2009,  21:16 Найти цитируемый пост)
id - должен совпадать, а дата должна быть >= effectiveDate.


Что мешает на JPAQuery запрос написать?


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
ShurikA
Дата 7.1.2009, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Цитата(powerOn @  7.1.2009,  21:02 Найти цитируемый пост)
Что мешает на JPAQuery запрос написать? 

Абсолютно ничего, тогда когда я хочу прото найти определённый обьект.

А теперь преставь себе что есть Customer у которого есть relationship (соответственно ManyToOne со стороны Customer, так как нужен только последний effective CustomerType)

В таком случае Customer должен выглядеть примерно вот так:
Код

@Entity
public class Customer implements Serializable {
    ...
    @ManyToOne
    @JoinTable(
        name="CustomerType",
        @JoinColumns({
            @JoinColumn(name="customerTypeId", referencedColumnName="id")
            //Как быть с effective date?
        })
    )
    private CustomerType custType;
    ...
}


Как ты понимаешь, если делать mapping только по одной колонке, то вряд ли мне принесётся effectiveCustomerType.




--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
ShurikA
Дата 8.1.2009, 09:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


Профиль
Группа: Завсегдатай
Сообщений: 1364
Регистрация: 29.10.2005
Где: Канада

Репутация: нет
Всего: 3



Есть ли в TopLink что то вроде @Where, как в Hibernate?


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
powerOn
Дата 8.1.2009, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 28
Всего: 159



Цитата(ShurikA @  8.1.2009,  09:54 Найти цитируемый пост)
Есть ли в TopLink что то вроде @Where, как в Hibernate?


Нет, Topllink реализует спецификацию JPA. Все что в спеке есть, все реализовано в Toplink (кроме Table per Concrete Class, ЕМНИП).

Хотелось бы для начала понять отношение сущностей в твоей доменной модели... что нужно в результате получить... может тогда какое решение и придумается...
 


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0980 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.