[
http://jira.jboss.com/jira/browse/HIBERNATE-36?page=comments#action_12339787 ]
Henrique Sousa commented on HIBERNATE-36:
-----------------------------------------
I still do not know why the many-to-many relations are cleared, however I was able to work
around the double flush by setting the flush mode to commit in all queries created due to
calls from the entity listener:
entityManager.createQuery("...").setFlushMode(FlushModeType.COMMIT).getSingleResult();
@ManyToMany associations removed after entity listener @PreUpdate
call
----------------------------------------------------------------------
Key: HIBERNATE-36
URL:
http://jira.jboss.com/jira/browse/HIBERNATE-36
Project: Hibernate
Issue Type: Bug
Environment: JBoss AS 4.0.4 CR2, Windows XP, JDK 1.5_05
Reporter: Henrique Sousa
Assigned To: Steve Ebersole
After calling EntityManager.merge() for an entity, its @EntityListeners @PreUpdate
methods are invoked. In the @PreUpdate method, locate another entity with @ManyToMany
associations. After the @PreUpdate method completes, the @ManyToMany associations are
cleaned. Below is some code which can be tested. Call the doSomething() method in the
RemoteInterfaceBean to perform the test.
/*** Bar.java */
package com.foo;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "TEST_BAR")
@EntityListeners(MyListener.class)
public class Bar {
private Integer id;
private String description;
private MyEntity entity;
@Id
public Integer getId() {
return id;
}
public String getDescription() {
return description;
}
@ManyToOne
public MyEntity getEntity() {
return entity;
}
public void setId(Integer id) {
this.id = id;
}
public void setDescription(String description) {
this.description = description;
}
public void setEntity(MyEntity entity) {
this.entity = entity;
}
public boolean equals(Object obj) {
if (!(obj instanceof Bar))
return false;
Integer other = ((Bar)obj).getId();
return id == null? other == null: id.equals(other);
}
public int hashCode() {
return getClass().getName().hashCode() + (id == null? 0: id.hashCode());
}
}
/*** MyEntity.java */
package com.foo;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name = "TEST_ENTITY")
public class MyEntity {
private Integer id;
private String description;
private Set<Target> targets;
@Id
public Integer getId() {
return id;
}
public String getDescription() {
return description;
}
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "TEST_ASSOCIATION",
joinColumns = {@JoinColumn(name = "ENTITY")},
inverseJoinColumns = {@JoinColumn(name = "TARGET")})
public Set<Target> getTargets() {
return targets;
}
public void setId(Integer id) {
this.id = id;
}
public void setDescription(String description) {
this.description = description;
}
public void setTargets(Set<Target> targets) {
this.targets = targets;
}
public boolean equals(Object obj) {
if (!(obj instanceof MyEntity))
return false;
Integer other = ((MyEntity)obj).getId();
return id == null? other == null: id.equals(other);
}
public int hashCode() {
return getClass().getName().hashCode() + (id == null? 0: id.hashCode());
}
}
/*** MyListener.java */
package com.foo;
import javax.naming.InitialContext;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
public class MyListener {
private static ThreadLocal<Object> running = new ThreadLocal<Object>();
@PrePersist
@PreUpdate
public void test(Bar bar) {
System.out.println("Started listener");
if (running.get() != null) {
System.out.println("Already running on this thread! Interrupting
listener");
return;
}
running.set(new Object());
try {
RemoteInterface ejb = (RemoteInterface)new InitialContext().lookup(
"WorldNet/RemoteInterfaceBean/remote");
MyEntity entity = ejb.getEntity();
bar.setEntity(entity);
System.out.println("entity description: " + entity.getDescription());
System.out.println("bar id: " + bar.getId());
System.out.println("Finished listener");
}
catch (Exception e) {
e.printStackTrace();
}
finally {
running.set(null);
}
}
}
/*** RemoteInterface.java */
package com.foo;
import javax.ejb.Remote;
@Remote
public interface RemoteInterface {
void doSomething();
MyEntity getEntity();
}
/*** RemoteInterfaceBean.java */
package com.foo;
import java.util.Random;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
public class RemoteInterfaceBean implements RemoteInterface {
static EntityManager staticPersistence;
@PersistenceContext
private EntityManager persistence;
public void doSomething() {
simplify();
Bar bar = new Bar();
bar.setId(5);
bar.setDescription("" + new Random().nextInt());
persistence.merge(bar); // MUST be merge, not persist!!!
}
public MyEntity getEntity() {
MyEntity entity = (MyEntity)persistence.createQuery(
"select x from MyEntity x join fetch x.targets").getSingleResult();
return entity;
}
private void simplify() {
staticPersistence = persistence;
}
}
/*** Target.java */
package com.foo;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "TEST_TARGET")
public class Target {
private Integer id;
private String description;
@Id
public Integer getId() {
return id;
}
public String getDescription() {
return description;
}
public void setId(Integer id) {
this.id = id;
}
public void setDescription(String description) {
this.description = description;
}
public boolean equals(Object obj) {
if (!(obj instanceof Target))
return false;
Integer other = ((Target)obj).getId();
return id == null? other == null: id.equals(other);
}
public int hashCode() {
return getClass().getName().hashCode() + (id == null? 0: id.hashCode());
}
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira