-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: Duplicate Roms in Many to Many relation
PostPosted: Wed Mar 04, 2009 3:07 pm 
Newbie

Joined: Wed Mar 04, 2009 2:02 pm
Posts: 4
Hi, I have I problem and don't even know how to google it. The fact is that I have a Class A than contains a ManyToMany relation with class B and a oneToMany relation with a Class C. When I try to get the class with non-lazy(querying A to have both list) behaviour the number of Rows of B get duplicated each time. If I get two list from separated I seem to work ok. I don't know what's happening:

The source code is as fallows:

package domain;

import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.CascadeType;

import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.IndexColumn;

Class A = Template
Class B = Editor
Class C = Resource

@Entity @AccessType("property")
@Table (name="Template")
public class Template implements java.io.Serializable {

/**
*
*/
private static final long serialVersionUID = 1L;
private int id;
private List<Resource> resources;
private List<Editor> editors;
private String MLSname;
private String description;
private HashSet<String> targetUrl;
private Date modifiedDate;
private Administrator administrator;



public Template(){
targetUrl = new HashSet<String>();
resources = new ArrayList<Resource>();
editors = new ArrayList<Editor>();
}

@Id @GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}


@ManyToMany(
targetEntity=domain.Editor.class,
cascade={CascadeType.MERGE}
)
@JoinTable(
name="TEMPLATE_EDITOR",
joinColumns=@JoinColumn(name="template_id"),
inverseJoinColumns=@JoinColumn(name="editor_id")
)
public List<Editor> getEditors() {
return editors;
}

public void setEditors(List<Editor> editors) {
this.editors = editors;
}

@ManyToOne
@JoinColumn(name="administrator_id")
@Cascade ( { org.hibernate.annotations.CascadeType.SAVE_UPDATE})
public Administrator getAdministrator() {
return administrator;
}

public void setAdministrator(Administrator administrator) {
this.administrator = administrator;
}


@OneToMany
@IndexColumn(name="indexResource")
@JoinColumn(name="template_id")
@Cascade ( { org.hibernate.annotations.CascadeType.ALL,
org.hibernate.annotations.CascadeType.SAVE_UPDATE,
org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public List<Resource> getResources() {
return resources;
}
public void setResources(List<Resource> resouces) {
this.resources = resouces;
}
public String getMLSname() {
return MLSname;
}
public void setMLSname(String sname) {
MLSname = sname;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public HashSet<String> getTargetUrl() {
return targetUrl;
}
public void setTargetUrl(HashSet<String> targetUrl) {
this.targetUrl = targetUrl;
}
public Date getModifiedDate() {
return modifiedDate;
}
public void setModifiedDate(Date modifiedDate) {
this.modifiedDate = modifiedDate;
}

}


package domain;
import java.util.List;
import java.util.ArrayList;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.IndexColumn;

@Entity @AccessType("property")
@Table (name="Editor")
public class Editor extends User {

/**
*
*/
private static final long serialVersionUID = 1L;

public List<Template> templates;

public Editor(){
templates = new ArrayList<Template>();
}


@ManyToMany(
mappedBy = "editors",
cascade={CascadeType.MERGE},
targetEntity = domain.Template.class
)
public List<Template> getTemplates() {
return templates;
}

public void setTemplates(List<Template> templates) {
this.templates = templates;
}
}


package domain;


import java.util.List;
import java.util.ArrayList;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.IndexColumn;

@Entity @AccessType("property")
@Table (name="Resource")
public class Resource extends RETSClass {

private static final long serialVersionUID = 1L;
private List<Classification> classifications;
private Template template;


public Resource(){
classifications = new ArrayList<Classification>();
}

@ManyToOne
@JoinColumn(name="template_id")
@Cascade ( { org.hibernate.annotations.CascadeType.SAVE_UPDATE})
public Template getTemplate() {
return template;
}



public void setTemplate(Template template) {
this.template = template;
}



@OneToMany
@JoinColumn(name="resource_id")
@IndexColumn(name="indexResource")
@Cascade ( { org.hibernate.annotations.CascadeType.ALL,
org.hibernate.annotations.CascadeType.SAVE_UPDATE,
org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public List<Classification> getClassifications() {
return classifications;
}

public void setClassifications(List<Classification> classifications) {
this.classifications = classifications;
}
}


and the sql query is this one:

crit.setFetchMode("editors",FetchMode.JOIN); crit.setFetchMode("resources",FetchMode.JOIN);
return (Template)DataAccessUtils.uniqueResult(getHibernateTemplate().findByCriteria(crit));

select this_.id as id7_5_, this_.MLSname as MLSname7_5_, this_.administrator_id as administ6_7_5_, this_.description as descript3_7_5_, this_.modifiedDate as modified4_7_5_, this_.targetUrl as targetUrl7_5_, administra2_.id as id0_0_, administra2_1_.expireDate as expireDate0_0_, administra2_1_.userName as userName0_0_, administra2_1_.userPassword as userPass4_0_0_, editors3_.template_id as template1_7_, editor4_.id as editor2_7_, editor4_.id as id0_1_, editor4_1_.expireDate as expireDate0_1_, editor4_1_.userName as userName0_1_, editor4_1_.userPassword as userPass4_0_1_, resources5_.template_id as template2_8_, resources5_.id as id8_, resources5_.indexResource as indexRes3_8_, resources5_.id as id3_2_, resources5_1_.beSpokeSystemName as beSpokeS2_3_2_, resources5_1_.templateName as template3_3_2_, resources5_.template_id as template2_6_2_, classifica6_.resource_id as resource2_9_, classifica6_.id as id9_, classifica6_.indexResource as indexRes3_9_, classifica6_.id as id3_3_, classifica6_1_.beSpokeSystemName as beSpokeS2_3_3_, classifica6_1_.templateName as template3_3_3_, classifica6_.resource_id as resource2_5_3_, fields7_.classification_id as classifi2_10_, fields7_.id as id10_, fields7_.indexField as indexField10_, fields7_.id as id3_4_, fields7_1_.beSpokeSystemName as beSpokeS2_3_4_, fields7_1_.templateName as template3_3_4_, fields7_.classification_id as classifi2_4_4_ from Template this_ left outer join Administrator administra2_ on this_.administrator_id=administra2_.id left outer join User administra2_1_ on administra2_.id=administra2_1_.id left outer join TEMPLATE_EDITOR editors3_ on this_.id=editors3_.template_id left outer join Editor editor4_ on editors3_.editor_id=editor4_.id left outer join User editor4_1_ on editor4_.id=editor4_1_.id left outer join Resource resources5_ on this_.id=resources5_.template_id left outer join RETSClass resources5_1_ on resources5_.id=resources5_1_.id left outer join Classification classifica6_ on resources5_.id=classifica6_.resource_id left outer join RETSClass classifica6_1_ on classifica6_.id=classifica6_1_.id left outer join Field fields7_ on classifica6_.id=fields7_.classification_id left outer join RETSClass fields7_1_ on fields7_.id=fields7_1_.id where this_.id=?


anyone know what could be happening? any ideas? I defenetly want to get the whole object at once. any help would be really apreciate! I've checked the BD and it looks allright with no duplicated entrys.

thank you again


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 3:18 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Try:

Code:
Criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 3:56 pm 
Newbie

Joined: Wed Mar 04, 2009 2:02 pm
Posts: 4
Hi, thank for the help,

I alreaday tryied Criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY) with any success :( thanks anyway for trying to help me out.

I didn't explain as well as I would like to. The first thing the query works allright, I don't save the object at all and the next time I call the function it returns me the double of elements and so on(it's the same object duplicated..) maybe it's using a cache or something... In the BDD everything looks allright. I just don't know what to do :(

I'm using spring and I make this call on my referenceData everytime the page is requested or reloaded!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 8:17 pm 
Newbie

Joined: Wed Mar 04, 2009 2:02 pm
Posts: 4
HI, I did new discovers from my problem. It happens after I do an update of the object. The fields are the same, they don't need any update but after the update query takes place I get the elements duplicated! any ideas? It's really anoying I don't know what to do. Am I missing any cascadetype in the @manytomany anotation?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 9:02 pm 
Regular
Regular

Joined: Tue Dec 30, 2008 8:14 pm
Posts: 50
If the Editors within a Template needs to be unique, try using a Set instead of List (and implement equals and hashcode).

LinHib.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 04, 2009 9:18 pm 
Newbie

Joined: Wed Mar 04, 2009 2:02 pm
Posts: 4
Hi, thanks for the help! In fact is I put a Set<> it works perfect but I want to use a list so I can sort elements as I get I from BDD.

I don't understand why after an update (when I add an element Resource) after I got duplicated Editors! If I execute de query like this

DetachedCriteria crit = DetachedCriteria.forClass(Resource.class);
crit.add(Restrictions.eq("id",idResource));
crit.setFetchMode("editors",FetchMode.JOIN);

insted of

DetachedCriteria crit = DetachedCriteria.forClass(Resource.class);
crit.add(Restrictions.eq("id",idResource));
crit.setFetchMode("editors",FetchMode.JOIN);
crit.setFetchMode("resources",FetchMode.JOIN);

I get the exact amount of editors but I want to collect both together. Could I be a trouble with annotations? I have been googeling long time and I can't find any similar trouble. I debugged my app and if after updating the object I try to get it from BDD all the existent Editors duplicated! don't know what else to do, I've been working all day in it but thanks for trying to help me out :) I really appreciate it


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 05, 2009 12:59 pm 
Regular
Regular

Joined: Tue Dec 30, 2008 8:14 pm
Posts: 50
Couple of things to check if you haven't already:
1, The FROM clause in the generated SQL has duplicate tables:
from Template this_
left outer join Administrator administra2_ on this_.administrator_id=administra2_.id
left outer join User administra2_1_ on administra2_.id=administra2_1_.id
left outer join TEMPLATE_EDITOR editors3_ on this_.id=editors3_.template_id
left outer join Editor editor4_ on editors3_.editor_id=editor4_.id
left outer join User editor4_1_ on editor4_.id=editor4_1_.id
left outer join Resource resources5_ on this_.id=resources5_.template_id
left outer join RETSClass resources5_1_ on resources5_.id=resources5_1_.id
left outer join Classification classifica6_ on resources5_.id=classifica6_.resource_id
left outer join RETSClass classifica6_1_ on classifica6_.id=classifica6_1_.id
left outer join Field fields7_ on classifica6_.id=fields7_.classification_id
left outer join RETSClass fields7_1_ on fields7_.id=fields7_1_.id


2, Some of these classes may need an equals method.

LinHib.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.