Hibernate version: Core 3.2.2 EM & A 3.2.1
WebSphere Application Server 6.1, WebSphere JTA, WebSphere DataSources, IBM DB2 V8
Flow: Request to add a Contact with id = '3456' comes through a WebService into a Stateless Session Bean (container transaction = required). EJB delegates to a Orchestrator. (Orchestrator gets an EntityManager and stores it on ThreadLocal). Then the Orchestrator makes an instance of Contact and calls the persist() method on the ContactDAO, passing the Contact instance to the persist() method. The persist() method on the DAO does nothing special in this case, just calls the persist() method on the EntityManager. (When leaving the Orchestrator, the EntityManager gets closed).
This works fine and gets persisted to the DataBase.
When the next request comes in and asks to add a Contact with the same key (3456). The persist() method doesn't throw an exception stating that a Contact entity with that key already exists, but only when the transaction is committed (in the EJB), the driver throws an exception stating that a record with a duplicate key already exists. Surely the persist() method must do this already?
(I understand Hibernate only flushes the DML at certain points, so is the only solution to get the persist() method to throw the exception immediately, to always do a flush() right after calling the persist() method? Waiting for the container to issues the commit and then only getting the duplicate key exception is too late in the process.)
@Entity
@Table(name = "CONTACT")
public class Contact {
private int calculateSomething;
private String firstName;
private String lastName;
private String email;
private String id;
@Column(name = "EMAIL")
public String getEmail() {
return email;
}
@Column(name = "FIRSTNAME")
public String getFirstName() {
return firstName;
}
@Column(name = "LASTNAME")
public String getLastName() {
return lastName;
}
public void setEmail(String string) {
email = string;
}
public void setFirstName(String string) {
firstName = string;
}
public void setLastName(String string) {
lastName = string;
}
@Id
@Column(name = "ID")
public String getId() {
return id;
}
public void setId(String string) {
id = string;
}
@Transient
public int getCalculateSomething() {
return calculateSomething;
}
public void setCalculateSomething(int calculateSomething) {
this.calculateSomething = calculateSomething + 300;
}
}
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/ ... ce_1_0.xsd" version="1.0">
<persistence-unit name="persistence" transaction-type="JTA">
<jta-data-source>java:comp/env/Hiber DataSource</jta-data-source>
<class>absa.sirius.test.entity.Contact</class>
<properties>
<property name="hibernate.archive.autodetection" value="none"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup"/>
<property name="hibernate.cache.use_second_level_cache" value="false"/>
</properties>
</persistence-unit>
</persistence>