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

Поиск:

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


Зануда
***


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

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



вот таким образом это не работает:
Код

@Entity
@Table(name = "CustomerType")
@NamedQueries({
    @NamedQuery(name = "CustomerType.findAll", query = "SELECT c FROM CustomerType c")
})
@PersistenceContext(unitName = "CRM-ejbPU", name = "persistence/em")
public class CustomerType extends CustomerTypeSuper {

    private static final long serialVersionUID = 1L;

    public CustomerType() {
    }

    @PreUpdate
    protected void preUpdate() {
        EntityManager em;
        System.out.println("PreUpdate");
        try {
            em = (EntityManager) (new InitialContext()).lookup("java:comp/env/persistence/em");

            Date editDate = new Date();
            //record to history
            CustomerTypeHist typeHist = new CustomerTypeHist();
            typeHist.cloneSource(this);
            typeHist.setExpirationDate(editDate);
            em.persist(typeHist);
            this.setEffectiveDate(editDate);
        } catch (NamingException ex) {
            ex.printStackTrace();
            Logger.getLogger(CustomerTypeSuper.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
...
}


Выдаёт:
Код

Exception [TOPLINK-28018] (Oracle TopLink Essentials - 2.0.1 (Build b04-fcs (04/11/2008))): oracle.toplink.essentials.exceptions.EntityManagerSetupException
Exception Description: predeploy for PersistenceUnit [CRM-ejbPU] failed.
Internal Exception: Exception [TOPLINK-7212] (Oracle TopLink Essentials - 2.0.1 (Build b04-fcs (04/11/2008))): oracle.toplink.essentials.exceptions.ValidationException
Exception Description: The attribute [effectiveDate] from the entity class [class crm.config.custType.entities.CustomerType] does not specify a temporal type. A temporal type must be specified for persistent fields or properties of type java.util.Date and java.util.Calendar.
javax.persistence.PersistenceException: Exception [TOPLINK-28018] (Oracle TopLink Essentials - 2.0.1 (Build b04-fcs (04/11/2008))): oracle.toplink.essentials.exceptions.EntityManagerSetupException
Exception Description: predeploy for PersistenceUnit [CRM-ejbPU] failed.
Internal Exception: Exception [TOPLINK-7212] (Oracle TopLink Essentials - 2.0.1 (Build b04-fcs (04/11/2008))): oracle.toplink.essentials.exceptions.ValidationException
Exception Description: The attribute [effectiveDate] from the entity class [class crm.config.custType.entities.CustomerType] does not specify a temporal type. A temporal type must be specified for persistent fields or properties of type java.util.Date and java.util.Calendar.
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:643)
        at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createContainerEntityManagerFactory(EntityManagerFactoryProvider.java:244)
        at com.sun.enterprise.server.PersistenceUnitLoaderImpl.load(PersistenceUnitLoaderImpl.java:149)
        at com.sun.enterprise.server.PersistenceUnitLoaderImpl.load(PersistenceUnitLoaderImpl.java:84)
...



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


software saboteur
****


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

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



Самый простой в данной ситуации (когда ну просто никак не избежать доступа к БД из слушателя сущностей) способ это создать EJB компонент с @Remote интерфейсом, в который будет инжектироваться EntityManager. Из слушателя получать доступ к бину.

Код

@Stateless
@Remote(IDaoBean.class)
public class DaoBean implements IDaoBean
{
    @PersistenceContext
    private EntityManager entityManager;

    public EntityManager getEntityManager()
    {
        return entityManager;
    }
}
 

В коде слушателя:
Код

@PreUpdate
protected void preUpdate() {
    InitialContext context = new InitialContext();
    IDaoBean iDaoBean = (IDaoBean) context.lookup(IDaoBean.class.getName());
}


Но! Мне такой подход не очень нравится. Прямо "Паблик Морозов" какой-то получился... никак не "сервис-локатор"... Поэтому я предлагаю общую логику работы с БД вынести в DaoBean и пусть он будет настоящим Dao сервисом.

Добавлено через 3 минуты и 11 секунд
Да, замечу, что доступ к EJB через JNDI весьма зависит от сервера приложений что вы используете. Данный вариант был описан для Glassfish. ЕМНИП, на JBoss необязательно делать бин с удаленным интрефейсом, можно и до локального простым лукапом достучаться.


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

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


Зануда
***


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

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



powerOn, 
Кстати, есть какая то причина что PreUpdate не вызывается если он прописан в MappedSuperclass, а не в самой сущности?


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


software saboteur
****


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

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



Цитата(ShurikA @  10.1.2009,  02:17 Найти цитируемый пост)
Кстати, есть какая то причина что PreUpdate не вызывается если он прописан в MappedSuperclass, а не в самой сущности? 


В спеке написано что можно и в mapped superclass слушателей определять. Давай код что-ли посмотрим...


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

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


Зануда
***


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

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



Цитата(powerOn @  10.1.2009,  12:27 Найти цитируемый пост)
В спеке написано что можно и в mapped superclass слушателей определять. Давай код что-ли посмотрим... 

Я где то выкопал что это баг. Сейчас не могу найти где?

Добавлено через 1 минуту и 57 секунд
Но на самом деле он мне в суперклассе не очень нужен. Можно было бы эту функцию сделать generic абсолютно для всех, но она будет немногим медленная.


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


Опытный
**


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

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



Похожую, если не именно эту, задачу решает проект Envers. Правда, он обладает кучей ограничений. К примеру, заточен под hibernate smile


--------------------
user posted image
PM MAIL Jabber   Вверх
ShurikA
Дата 12.1.2009, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зануда
***


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

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



Воткнулся в очередную проблемму:
Код

Exception Description: The attribute [effectiveDate] from the entity class [class crm.config.custType.entities.CustomerType] does not specify a temporal type. A temporal type must be specified for persistent fields or properties of type java.util.Date and java.util.Calendar.


При этом CustomerType выглядет так:
Код

@MappedSuperclass
public class CustomerTypeSuper implements Serializable {

    protected static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    protected Integer id;
    @Basic(optional = false)
    @Column(name = "type", nullable = false, length = 50)
    protected String type;
    @Basic(optional = false)
    @Column(name = "active", nullable = false)
    protected boolean active;
    @Basic(optional = false)
    @Column(name = "effectiveDate", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    protected Date effectiveDate;
    @Column(name = "expirationDate")
    @Temporal(TemporalType.TIMESTAMP)
    protected Date expirationDate;
    @Basic(optional = false)
    @Column(name = "operator", nullable = false, length = 50)
    protected String operator;

    public CustomerTypeSuper() {
    }

    public CustomerTypeSuper(Integer id) {
        this.id = id;
    }

    public CustomerTypeSuper(Integer id, String type, boolean active, Date effectiveDate, String operator) {
        this.id = id;
        this.type = type;
        this.active = active;
        this.effectiveDate = effectiveDate;
        this.operator = operator;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public boolean isActive() {
        return active;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public Date getEffectiveDate() {
        return effectiveDate;
    }

    public void setEffectiveDate(Date effectiveDate) {
        this.effectiveDate = effectiveDate;
    }

    public Date getExpirationDate() {
        return expirationDate;
    }

    public void setExpirationDate(Date expirationDate) {
        this.expirationDate = expirationDate;
    }

    public String getOperator() {
        return operator;
    }

    public void setOperator(String operator) {
        this.operator = operator;
    }

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

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof CustomerTypeSuper)) {
            return false;
        }
        CustomerTypeSuper other = (CustomerTypeSuper) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "crm.config.custType.entities.CustomerType[id=" + id + "]";
    }
}


Код

@Entity
@Table(name = "CustomerType", catalog = "CRM", schema = "")
@NamedQueries({@NamedQuery(name = "CustomerType.findAll", query = "SELECT c FROM CustomerType c")})
public class CustomerType extends CustomerTypeSuper {

    private static final long serialVersionUID = 1L;

    public CustomerType() {
    }

    @PreUpdate
    protected void preUpdate() {
        Date editDate = new Date();
        CustomerTypeHist histType = new CustomerTypeHist();
        histType.cloneSource(this);
        histType.setExpirationDate(editDate);
        this.setEffectiveDate(editDate);
        try {
            //find the EJC to save the history entity
            InitialContext context = new InitialContext();
            CustomerTypeRemote aMgr = (CustomerTypeRemote) context.lookup(CustomerTypeRemote.class.getName());
            aMgr.persist(histType);
        } catch (NamingException ex) {
            ex.printStackTrace();
            Logger.getLogger(CustomerType.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

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

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof CustomerType)) {
            return false;
        }
        CustomerType other = (CustomerType) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "crm.config.custType.entities.CustomerType[id=" + id + "]";
    }
}



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


Зануда
***


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

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



Если анотацию @PreUpdate убрать, то всё ОК.   smile 


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


software saboteur
****


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

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



все аннотации либо всегда указывают на методах, либо всегда на полях. т.е. изначально выбирается один стиль. в твоем случае нужно указывать на методах, поскольку @PreUpdate на поле нельзя указать. 


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

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


Зануда
***


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

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



powerOn, 
То есть мне нужно все мои анотации перенести на методы?
Это достаточно сделать только в одном классе?


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


software saboteur
****


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

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



Цитата(ShurikA @  13.1.2009,  10:04 Найти цитируемый пост)
powerOn, 
То есть мне нужно все мои анотации перенести на методы?
Это достаточно сделать только в одном классе? 


Попробуй. Если будет не достаточно, то значит во всех.



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

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


Зануда
***


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

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



если класс(Entity)  порождается от папы а папа в свою очередь от его папы, и папа и дедушка должны быть @MappedSuperclass ?


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


Зануда
***


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

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



Цитата(powerOn @  13.1.2009,  08:55 Найти цитируемый пост)
все аннотации либо всегда указывают на методах, либо всегда на полях. т.е. изначально выбирается один стиль. в твоем случае нужно указывать на методах, поскольку @PreUpdate на поле нельзя указать. 

OK, вроде всё работает и вызывается.

Следуюшая проблемма smile
выглядит так как будто @PreUpdate вызывается после того как поля уже поменянны, как можно отловить момент до того как они меняются?

Это сообщение отредактировал(а) ShurikA - 14.1.2009, 10:34


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


software saboteur
****


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

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



Цитата(ShurikA @  14.1.2009,  10:05 Найти цитируемый пост)
выглядит так как будто @PreUpdate вызывается после того как поля уже поменянны, как можно отловить момент до того как они меняются?


Не понял. PreUpdate вызывается перед обновлением данных в БД.



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

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


Зануда
***


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

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



Цитата(powerOn @  14.1.2009,  11:18 Найти цитируемый пост)
Не понял. PreUpdate вызывается перед обновлением данных в БД.

Правильно, но поля обьекта уже изменены к тому времени.


--------------------
Если долго мучиться, что нибудь получится...
user posted image
PM MAIL WWW ICQ Skype   Вверх
Страницы: (4) Все 1 2 [3] 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.0767 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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