Hello.
I'm (still) trying to use the entity listeners to keep an history of the changes made to a certain type of entity.
The code for my test entity is as follows:
--------------------------------------Car-----------------------------------------
package ejb3.tests.entitylistener.persistence;
import ...
@Entity
@Table(name = "CAR")
public class Car {
private static long initialId = 0;
@EmbeddedId
private CarId id;
@Column(name = "HP")
private int horsePower;
//I would generate the in key in @PrePersist, but hibernate
//checks the key before calling it
public Car() {
this.id = new CarId();
}
public CarId getId() {
return this.id;
}
public void setId(CarId id) {
this.id = id;
}
public int getHorsePower() {
return this.horsePower;
}
public void setHorsePower(int horsePower) {
this.horsePower = horsePower;
}
@PrePersist
public void createNewId() {
System.out.println("PrePersist Me: " + this);
if(this.id.getId() == 0) {
synchronized(Car.class) {
this.id.setId(++initialId);
this.id.setVersion(1);
}
}
}
@PostPersist
public void createHistoricRecord() throws NamingException {
System.out.println("PostPersist Me: " + this);
if(this.id.getVersion() == 1) {
synchronized(Car.class) {
InitialContext ic = new InitialContext();
Object o = ic.lookup( "java:/EntityListenerTestOtherEntityManager");
EntityManager em = (EntityManager)o;
Car copy = new Car();
long carIdId = this.id.getId();
int carIdVersion = this.id.getVersion();
copy.id = new CarId(carIdId, carIdVersion - 1);
System.out.println("PostPersist The Copy: " + copy);
em.persist(copy);
em.flush();
}
}
}
}
----------------------------------------CarId-------------------------------------
package ejb3.tests.entitylistener.persistence;
import ...
@Embeddable
public class CarId implements java.io.Serializable {
private static final long serialVersionUID = 1;
private long id;
private int version;
public CarId() {
}
public CarId(long id, int version) {
this.id = id;
this.version = version;
}
@Column(name="ID", nullable=false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
@Column(name="VERSION", nullable=false)
public int getVersion() {
return this.version;
}
public void setVersion(int version) {
this.version = version;
}
public boolean equals(Object other) {
if ( (this == other ) ) return true;
if ( (other == null ) ) return false;
if ( !(other instanceof CarId) ) return false;
CarId castOther = ( CarId ) other;
return (this.getId()==castOther.getId())
&& (this.getVersion()==castOther.getVersion());
}
public int hashCode() {
int result = 17;
result = 37 * result + (int) this.getId();
result = 37 * result + this.getVersion();
return result;
}
}
----------------------------------------------------------------------------------
If I create a new instance of Car am call EntityManager.persist on that instance, I get an exception, like:
Exception in thread "main" javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [ejb3.tests.entitylistener.persistence.Car#ejb3.tests.entitylistener.persistence.CarId@5b0e] ...
The output on the JBoss window is the following:
15:49:50,430 INFO [STDOUT] PrePersist Me: ejb3.tests.entitylistener.persistence.Car@c98b07
15:49:50,852 INFO [STDOUT] PostPersist Me: ejb3.tests.entitylistener.persistence.Car@c98b07
15:49:50,852 INFO [STDOUT] PostPersist The Copy: ejb3.tests.entitylistener.persistence.Car@f2ff9b
15:49:50,852 INFO [STDOUT] PrePersist Me: ejb3.tests.entitylistener.persistence.Car@f2ff9b
15:49:50,852 INFO [STDOUT] PostPersist Me: ejb3.tests.entitylistener.persistence.Car@c98b07
15:49:50,852 INFO [STDOUT] PostPersist The Copy: ejb3.tests.entitylistener.persistence.Car@16b5518
15:49:50,852 INFO [STDOUT] PrePersist Me: ejb3.tests.entitylistener.persistence.Car@16b5518
Please clarify me something: shouldntt the second @PostPersist be applied to the Car copy? I thing it should, but as you can see it's being applyed again to the original Car. Is it a bug or is this the correct behaviour? If it's a bug, is there anyway to circumvent it?
I will now try to create a history records using a native SQL query.
Thanks in advance for any input.
Hugo Oliveira
hugom.oliveira.ext@siemens.com