powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / EntityManager и другие непонятки
1 сообщений из 1, страница 1 из 1
EntityManager и другие непонятки
    #37756526
recvezitor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это продолжение вот этой темы http://www.sql.ru/forum/actualthread.aspx?tid=924416 постю заново, потому что там название не красивое. Краткое содержание предыдущих серий.
Сперва был hibernate 3.6.2 и был совсем непонятный эксепшен:
java.lang.ClassCastException: org.hibernate.action.DelayedPostInsertIdentifier cannot be cast to java.lang.Long
Совсем было не понятно, что это такое.
Затем обновился на hibernate 3.6.10 и эксепшен изменился:
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist
Стало понятно, что что-то не так с EntityManager'ом или с сессией.
Собственно код, который выкидывал эти исключения:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
public void registerCard(DenariiProductDao denariiProductDao, DenariiCurrencyDao denariiCurrencyDao, DenariiCardDao denariiCardDao, int securityCode, long san, String accountNumber, String currencyCode, String pin, String productName, String cardNumberPrefix, Long cardSanPrefix) {
        DenariiCard card = new DenariiCard();
        card.setBalance(0D);
        card.setHoldBalance(0D);
        card.setAccountNumber(accountNumber);
        card.setSan(san);
        DenariiProduct product = denariiProductDao.findProductByCode(productName);
        if (product == null) {
            throw new InvalidProductException();
        }
        card.setProduct(product);
        DenariiCurrency usd = denariiCurrencyDao.findCurrencyByCode(currencyCode);
        if (usd == null) {
            throw new CurrencyCodeException();
        }
        card.setCurrency(usd);
        card.setPin(pin);
        assignExpirationDate(card);
        card.setCardStatus(DenariiCardStatus.INACTIVE);
        card.setSecurityCode(securityCode);
        card.setSan(System.currentTimeMillis());

        denariiCardDao.persist(card);  //<--- Здесь зло

        denariiCardDao.refresh(card);
        card.setSan(cardSanPrefix + card.getId());
        card.setAccountNumber(createAccountNumber(cardNumberPrefix, card.getId()));
        denariiCardDao.merge(card);
    }



в дао совсем ничего нет необычного:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
public abstract class AbstractDao<E, PK extends Serializable> implements Dao<E, PK> {

    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }

    @PersistenceContext(unitName = "DenariiSimulator")
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public abstract Class<E> getEntityClass();

    @Override
    public void persist(E e) {
        getEntityManager().persist(e);
    }

    @Override
    public E merge(E e) {
        return getEntityManager().merge(e);
    }

    @Override
    public void refresh(E e) {
        getEntityManager().refresh(e);
    }
 }



Были предложения вместо persist использовать merge, но ничего кардинльно не изменилось и записи в БД не появилялось.

Я сперва решил проверить, открыта ли сессия хибернейтовская и попробовал в методы дао встроить такую штуку:
Код: java
1.
2.
3.
EntityManager em = getEntityManager();
org.hibernate.Session hSession = (Session) em.getDelegate();
hSession.isOpen();


Ну как догадываются зрители, сессия была закрыта, тогда я решил в ручную открывать сессию и комитить:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
EntityManager em = getEntityManager();
        org.hibernate.Session hSession = (Session) em.getDelegate();
        org.hibernate.classic.Session session = hSession.getSessionFactory().openSession();
        session.setFlushMode(FlushMode.MANUAL);
        ManagedSessionContext.bind(session);
        Transaction tr = session.beginTransaction();
        session.saveOrUpdate(e);
        tr.commit();
        session.close();


И это сработало, с маленьким ограничением: база должна быть пустой. Он почему то забывал существующие id'шники.
Тогда я где-то натолкнулся на похожую проблему и там был совет изменить настройки EntityManager'а:
Код: xml
1.
2.
<context:annotation-config/>
    <tx:annotation-driven mode="aspectj" proxy-target-class="true" transaction-manager="denariiTransactionManager"/> <!--было -->



Код: xml
1.
2.
<context:annotation-config/>
   <tx:annotation-driven transaction-manager="denariiTransactionManager"/><!--стало-->


Сделав так, я сумел получить такое же поведение как и с ручным открытием сессии, но вернувшись к обычному вызову getEntityManager().persist(e);
Т.е. сейчас у меня нормально добавляются записи в таблицу если там нет данных. Но они там есть. Внимание вопрос, почему хибернейт забыл id'шники?
Еще я от отчаяния добавил в код перед вызовом persist, такую штуку:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        if (getEntityManager().isOpen()) {
            System.out.println("ITSOPEN_PERSIST");
        } else {
            System.out.println("SUCK_NOTOPEN_PERSIST");
        }
        if (getEntityManager().contains(e)) {
            System.out.println("ITSCONTAINSENTITYIN_PERSIST");
        } else {
            System.out.println("SUCK_NOTCONTAIN_PERSIST");
        }



И EntityManager у меня всегда открытый, но НЕ содержит сущности. Может это натолкнет кого на мысль.
Спасибо за внимание, просто надо было выговориться и собрать в кучу все что натворил.
Сейчас думаю изменить тип генератора id с identity на sequence...
...
Рейтинг: 0 / 0
1 сообщений из 1, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / EntityManager и другие непонятки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]