У меня странная ошибка двойной вставки в БД. У меня есть следующие классы:
- TestEntity - сущность с методами @PrePersist и @PostPersist.
- Аудитория - аудиторская организация
- Набор данных - интерфейс DatasetBean
- DatasetBean - bean-компонент без состояния, который реализует набор данных
- DatasetFactory - экземпляр EJB набора данных (поиск)
Я поставил проблему в тесте junit (я использую встроенный Glassfish):
@Test
public void test() throws NamingException {
Dataset<TestEntity> dataset = this.lookupBy(DatasetBean.class);
Assert.assertNotNull(dataset);
TestEntity t = new TestEntity();
t.setName(UUID.randomUUID().toString());
dataset.insert(t);
System.out.println("end");
}
Ход теста следующий:
После получения объекта набора данных я пытаюсь вставить объект TestEntity
@ Stateless
@EJB (name = "...", beanInterface = Dataset.class)
открытый класс DatasetBean реализует набор данных {
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
@Override
public void insert(T entidade) {
LOG.info("Inserting: " + entidade);
entityManager.persist(entidade);
}
//...
}
Используя DatasetFactory, я пытаюсь вставить объект Auditing в метод @PostPersist объекта TestEntity
открытый класс DatasetFactory {
public static Dataset createDataset () {
пытаться {
return (набор данных) new InitialContext (). lookup ("...");
} catch (Exex ex) {
бросить новое RuntimeException (ex);
}
}
}
@ Entity
открытый класс TestEntity реализует MyEntity {
@Я бы
закрытый целочисленный идентификатор;
личное строковое имя;
// устанавливает и получает
@PrePersist
public void fillId() {
if (getId() == null || getId() == 0) {
Dataset d = DatasetFactory.createDataset();
Integer i = (Integer) d.fetchJPQLFirstResult("SELECT MAX(te.id) FROM TestEntity te");
if (i == null || i < 100) {
setId(100);
} else {
setId(i + 1);
}
}
}
@PostPersist
public void audit() {
Dataset<Auditing> dataset = DatasetFactory.createDataset();
// dataset.getEntityManager().clear();
Auditing auditing = new Auditing();
auditing.setIdEntidade(String.valueOf(this.getId()));
dataset.insert(auditing);
}
}
@ Entity
Общественный класс Auditoria реализует MyEntity {
@Я бы
@GeneratedValue (стратегии = GenerationType.IDENTITY)
закрытый целочисленный идентификатор;
приватная строка idEntity;
// устанавливает и получает
}
открытый интерфейс MyEntity расширяет Serializable {
Integer getId ();
}
Вход
ИНФОРМАЦИЯ: внедренный был успешно развернут в 47.154 миллисекундах.
PlainTextActionReporterSUCCESSDescription: развернуть AdminCommandApplication, развернутый с внедренным именем.
2012-01-06 02: 56: 54,826 [главная] ИНФОРМАЦИЯ com.joaosavio.model.db.DatasetBean (DatasetBean.java:30) - Вставка: TestEntity {id = null, name = ea5c2af4-0ca7-48a2- a82a-dbf582c570a9}
Hibernate: выберите max (testentity0_.id) в качестве col_0_0_ из TestEntity testentity0_
Hibernate: вставить в TestEntity (имя, идентификатор) значения (?,?)
2012-01-06 02: 56: 56,344 [главная] ИНФОРМАЦИЯ com.joaosavio.model.db.DatasetBean (DatasetBean.java:30) - Вставка: Auditoria {id = null, idEntidade = 100}
Hibernate: вставить в TestEntity (имя, идентификатор) значения (?,?)
2012-01-06 02: 56: 56,350 [main] WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper (SqlExceptionHelper.java:143) - Ошибка SQL: 2627, SQLState: 23000
2012-01-06 02: 56: 56,352 [main] ОШИБКА org.hibernate.engine.jdbc.spi.SqlExceptionHelper (SqlExceptionHelper.java:144) - Нарушение ограничения PRIMARY KEY 'PK_ TestEntity _76818E95. Невозможно вставить повторяющийся ключ в объект 'dbo.TestEntity'.
06.01.2012 02:56:56 com.sun.ejb.containers.BaseContainer postInvoke
ПРЕДУПРЕЖДЕНИЕ: системное исключение произошло во время вызова метода EJB DatasetBean public void com.joaosavio.model.db.DatasetBean.insert (java.lang.Object)
javax.ejb.TransactionRolledbackLocalException: исключение, сгенерированное из bean-компонента
...
Причина: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Нарушение ограничения PRIMARY KEY 'PK_ TestEntity _76818E95'. Невозможно вставить повторяющийся ключ в объект 'dbo.TestEntity'.
...
Вызвано: org.hibernate.exception.ConstraintViolationException: Нарушение ограничения PRIMARY KEY 'PK_ TestEntity _76818E95'. Невозможно вставить дубликат ключа в объект "dbo.TestEntity".
Вопросы:
Полагаясь на то, что все работает нормально, если я очищаю диспетчер сущностей перед вставкой сущности Auditing (закомментированный код в методе @PostPersist в TestEntity), я считаю, что TestEntity застревает в транзакции.
Что я делаю не так ???