[jboss-user] [Persistence, JBoss/CMP, Hibernate, Database] - Duplicate Objects in Entity's mapped OnetoMany collection

jfrankman do-not-reply at jboss.com
Thu May 22 11:21:56 EDT 2008


What can cause duplicate objects to show up in a collection when the SQL data itself is fine?  I have a problem where duplicate java objects are showing up in a @OneToMany relationship on one of my entities. I need to figure out why these duplicate objects show up in my collection. 

Here is the model I am working with:

-ClientVO has a recursive relationship with itself where one ClientVO object may be the parent one or more other ClientVO ojbects. 
-Each ClientVO object has a OnetoMany relationship with ClientLocationVO. The ClientLocationVO object has a composite key as an identifier.

In the database ClientVO with id 76237 is is the parent of two other ClientVO objects:


anonymous wrote : ClientID 		Name 		ParentClientID
  | 76237		Doe Household	NULL
  | 123456	Jane Doe		76237
  | 789456	John Doe		76237

Client 76237 has three ClientLocationVO records

anonymous wrote : ClientID	LocationID	LocationType
  | 76237		111		1
  | 76237		333		2
  | 76237		555		3

The problem that I am having is that when the following EJB query is run, there are six client members in the client members collection instead of just two:


@NamedQueries( { @NamedQuery(name = "findClientByIdFetchGraph", 
  | 	query = "select distinct client from ClientVO client "
  | 		+ "left join fetch client.entityLocations entityLocation "
  | 		+ "left join fetch client.clientMembers clientMember " 
  | 		+ "where (client.id = :id) ")
  | })

		for (ClientVO subClient : client.getClientMembers())
  | 		{
  | 			System.out.println(subClient.getSearch());
  | 		}

anonymous wrote : Output:
  | DOE JANE
  | DOE JOHN
  | DOE JANE
  | DOE JOHN
  | DOE JANE
  | DOE JOHN

However, if I change the query and remove the client locations join, the correct number of clientmembers is returned in my collection:


@NamedQueries( { @NamedQuery(name = "findClientByIdFetchGraph", 
  | 	query = "select distinct client from ClientVO client "
  | 		+ "left join fetch client.clientMembers clientMember " 
  | 		+ "where (client.id = :id) ")
  | })


		for (ClientVO subClient : client.getClientMembers())
  | 		{
  | 			System.out.println(subClient.getSearch());
  | 		}

anonymous wrote : Output:
  | DOE JANE
  | DOE JOHN

Something is wrong with my query or with my mappings that is causing duplicate objects to show up in the clientMembers collection when the database only contains two records. This only happens when I include a join to the clientLocations in the query. I am looking for ideas as to why this is happening and what I can do about it. Any thoughts or suggestions is appreciated. Here are the two entities in question:



@Entity
  | @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
  | @DiscriminatorColumn(name = "CLNTTYPE", discriminatorType = DiscriminatorType.STRING)
  | @Table(name = "FBCLIENT")
  | @Name("client")
  | @Scope(ScopeType.SESSION)
  | public class ClientVO implements Serializable
  | {
  | 
  | 	/*
  | 	 * , @NamedQuery(name = "findLendersByName", query = "select distinct client
  | 	 * from ClientVO client " + "left join fetch client.roles role " + "left
  | 	 * join fetch client.entityLocations entityLocation " + "left join fetch
  | 	 * entityLocation.locationType locationType " + "left join fetch
  | 	 * entityLocation.location location " + "where (client.search like :name and
  | 	 * role.id=1) ")
  | 	 * 
  | 	 * 
  | 	 */
  | 	private static final long serialVersionUID = 2285612284592204149L;
  | 
  | 	private Long id;
  | 	private String notes;
  | 	private String clientType;
  | 	private String memberNumber;
  | 	private Set<ClientLocationVO> entityLocations = new HashSet<ClientLocationVO>();
  | 	private String search;
  | 	private List<ClientVO> clientMembers = new ArrayList<ClientVO>();
  | 
  | 	/**
  | 	 * Retrieves the value of the id attribute in the class
  | 	 * 
  | 	 * @return id (Long)
  | 	 */
  | 	@Id
  | 	@NotNull
  | 	@Column(name = "CLIENTID")
  | 	public Long getId()
  | 	{
  | 		return id;
  | 	}
  | 
  | 	@OneToMany(mappedBy = "parentClient", fetch = FetchType.LAZY)
  | 	public List<ClientVO> getClientMembers()
  | 	{
  | 		return clientMembers;
  | 	}
  | 
  | 	@ManyToOne()
  | 	@JoinColumn(name = "parentclientid")
  | 	public ClientVO getParentClient()
  | 	{
  | 		return parentClient;
  | 	}
  | 
  | 	public void setClientMembers(final List<ClientVO> inChildMembers)
  | 	{
  | 		this.clientMembers = inChildMembers;
  | 	}
  | 
  | 	public void setParentClient(final ClientVO inParentClient)
  | 	{
  | 		this.parentClient = inParentClient;
  | 	}
  | 
  | 
  | 
  | 	@OneToMany
  | 	@JoinColumns( { @JoinColumn(name = "clientid", referencedColumnName = "CLIENTID") })
  | 	public Set<ClientLocationVO> getEntityLocations()
  | 	{
  | 		return entityLocations;
  | 	}
  | }
  | 
  | @Entity
  | @Table(name = "FBCLNTLOC")
  | @Name("clientLocation")
  | public class ClientLocationVO implements Serializable
  | {
  | 	private static final long serialVersionUID = 2285612284592204149L;
  | 
  | 	private ClientLocationPk id = new ClientLocationPk();
  | 	private ClientVO client;
  | 	private Location location;
  | 	private LocationType locationType;
  | 
  | 	public ClientLocationVO(final LocationType inLocationType, final ClientVO inClient, final Location inLocation)
  | 	{
  | 		this.locationType = inLocationType;
  | 		this.client = inClient;
  | 		this.location = inLocation;
  | 
  | 		this.id.setClientId(inClient.getId());
  | 		this.id.setLocationId(inLocation.getId());
  | 		this.id.setLocationTypeId(inLocationType.getId());
  | 
  | 		// Guarantee referential integrity
  | 		// client.getEntityLocations().add(this);
  | 		inLocation.getEntityLocations().add(this);
  | 	}
  | 
  | 	@Id
  | 	public ClientLocationPk getId()
  | 	{
  | 
  | 		return id;
  | 	}
  | 
  | 	@ManyToOne(cascade = CascadeType.ALL)
  | 	@JoinColumn(name = "CLIENTID")
  | 	public ClientVO getClient()
  | 	{
  | 		return client;
  | 	}
  | 
  | 	@ManyToOne(cascade = CascadeType.ALL)
  | 	@JoinColumn(name = "LOCATIONID")
  | 	public Location getLocation()
  | 	{
  | 		return location;
  | 	}
  | 
  | 	@ManyToOne(cascade = CascadeType.ALL)
  | 	@JoinColumns( { @JoinColumn(name = "LOCTYPEID", insertable = false, updatable = false) })
  | 	public LocationType getLocationType()
  | 	{
  | 		return locationType;
  | 	}
  | 
  | 	public void setId(final ClientLocationPk inId)
  | 	{
  | 		this.id = inId;
  | 	}
  | 
  | 	@Override
  | 	public boolean equals(final Object obj)
  | 	{
  | 		if (this == obj)
  | 		{
  | 			return true;
  | 		}
  | 		if (obj == null)
  | 		{
  | 			return false;
  | 		}
  | 		if (getClass() != obj.getClass())
  | 		{
  | 			return false;
  | 		}
  | 
  | 		final ClientLocationVO other = (ClientLocationVO) obj;
  | 
  | 		if (this.client == null)
  | 		{
  | 			if (other.client != null)
  | 			{
  | 				return false;
  | 			}
  | 		}
  | 		else if (!this.client.equals(other.client))
  | 		{
  | 			return false;
  | 		}
  | 
  | 		if (this.location == null)
  | 		{
  | 			if (other.location != null)
  | 			{
  | 				return false;
  | 			}
  | 		}
  | 		else if (!this.location.equals(other.location))
  | 		{
  | 			return false;
  | 		}
  | 
  | 		if (this.locationType == null)
  | 		{
  | 			if (other.locationType != null)
  | 			{
  | 				return false;
  | 			}
  | 		}
  | 		else if (!this.locationType.equals(other.locationType))
  | 		{
  | 			return false;
  | 		}
  | 
  | 		return true;
  | 	}
  | 
  | 	@Override
  | 	public int hashCode()
  | 	{
  | 		final int prime = 31;
  | 		int result = 1;
  | 
  | 		result = prime * result + ((this.client == null) ? 0 : this.client.hashCode());
  | 		result = prime * result + ((this.location == null) ? 0 : this.location.hashCode());
  | 		result = prime * result + ((this.locationType == null) ? 0 : this.locationType.hashCode());
  | 
  | 		return result;
  | 	}
  | 
  | 
  | }



View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4152742#4152742

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4152742



More information about the jboss-user mailing list