[jboss-jira] [JBoss JIRA] Commented: (HIBERNATE-36) @ManyToMany associations removed after entity listener @PreUpdate call

Henrique Sousa (JIRA) jira-events at jboss.com
Wed Jul 19 10:42:11 EDT 2006


    [ 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

        



More information about the jboss-jira mailing list