[jboss-user] [EJB 3.0] - ManyToMany relationship do not work properly

fla83tn do-not-reply at jboss.com
Tue Nov 20 11:56:06 EST 2007


Hi to all,
I'm working on jboss 4.2.1GA and I'm stuck with a simple ManyToMany relationship..

I have this relation between Users and Sources (of rss feeds - URLs in practice). I followed all tutorial about how to do it and I tried a lot of solutions but I can't figure out why it doesn't work!

Here's the entity class User:

package nc.entities.user;
  | 
  | import javax.persistence.*;
  | import java.util.Collection;
  | import java.util.ArrayList;
  | import nc.entities.source.Source;
  | 
  | 
  | @Entity(name="User")
  | @Table(name="USERS")
  | //Named queries expressed the Java Persistence query language
  | @NamedQueries(
  |  {  @NamedQuery(
  |       name="User.findByNickName",
  |       query="SELECT u FROM User u WHERE u.nick LIKE :nick"
  |     ), 
  |     @NamedQuery(
  | 	name="User.deleteAll",
  | 	query="DELETE FROM User u"
  |     ),
  |     @NamedQuery(
  | 	name="User.selectAll",
  | 	query="SELECT u FROM User u"
  |     )
  | 
  |   }
  | )
  | public class User {
  | 
  |     private int userId;
  |     private String name;
  |     private String password;
  |     private String nick;
  |     private Collection<Source> sources;
  |     
  |     /** Entities must have a public no-arg constructor */
  |     public User() {  }
  | 
  |     @Id
  |     @TableGenerator(name="USER_ID_GENERATOR",
  |             table="ID_GEN",
  |             pkColumnName="GEN_KEY",
  |             valueColumnName="GEN_VALUE",
  |             pkColumnValue="USER_ID",
  |             allocationSize=1)
  |     @GeneratedValue(strategy=GenerationType.TABLE,generator="USER_ID_GENERATOR")
  |     public int getUserId()     { return userId;   }
  |     public String getName()    { return name;     }
  |     public String getPassword(){ return password; }
  |     public String getNick()    { return nick;     }
  | 
  |     public void setUserId(int id)	    { this.userId=id;	      }
  |     public void setName(String name)        { this.name=name;         }
  |     public void setPassword(String password){ this.password=password; }
  |     public void setNick(String nick)        { this.nick=nick;         }
  | 
  |     // N:M bidirectional - TO
  | @ManyToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY,mappedBy="users",targetEntity=Source.class)
  |     public Collection<Source> getSources() { return sources;} 
  |     public void setSources(Collection<Source> sources) { this.sources = sources;}
  | 
  | }

and here's the code of entity Source
package nc.entities.source;
  | 
  | 
  | import javax.persistence.*;
  | import java.util.Collection;
  | import java.util.ArrayList;
  | import nc.entities.user.User;
  | import nc.entities.feed.Feed;
  | 
  | @Entity(name="Source")
  | @Table(name="SOURCES")
  | @NamedQueries(
  |  {  @NamedQuery(
  |       name="Source.findByUrl",
  |       query="SELECT s FROM Source s WHERE s.url LIKE :url"
  |     ), 
  |     @NamedQuery(
  | 	name="Source.deleteAll",
  | 	query="DELETE FROM Source s"
  |     )
  |  }
  | )
  | public class Source {
  | 
  |     private int sourceId;
  |     private String url;
  |     private Collection<User> users;
  |     private Collection<Feed> feeds;
  | 
  |      /** Entities must have a public no-arg constructor */
  |     public Source(){ }
  | 
  |     public void setUrl(String url){this.url=url;}
  |     public void setSourceId(int id){this.sourceId=id;}
  | 
  |     @Id
  |     @TableGenerator(name="SOURCE_ID_GENERATOR",
  |             table="ID_GEN",
  |             pkColumnName="GEN_KEY",
  |             valueColumnName="GEN_VALUE",
  |             pkColumnValue="SOURCE_ID",
  |             allocationSize=5)
  |     @GeneratedValue(strategy=GenerationType.TABLE,generator="SOURCE_ID_GENERATOR")
  |     public int getSourceId(){return sourceId;}
  |     public String getUrl()  {return url;}
  | 
  |     // N:M: bidirectional - FROM
  |     @ManyToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, targetEntity=User.class)
  |      //@JoinTable(name="SOURCE_USER")
  |     @JoinTable(name = "SOURCE_USER",
  |                joinColumns = @JoinColumn(name = "SOURCE_ID", referencedColumnName="sourceId"),
  |                inverseJoinColumns = @JoinColumn(name = "USER_ID",  referencedColumnName="userId"))
  |     public Collection<User> getUsers() { return users; } 
  |     public void setUsers(Collection<User> users) { this.users = users;  }
  | 
  |     // 1:N unidirectional: FROM
  |     @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY)
  |     public Collection<Feed> getFeeds() { return feeds; } 
  |     public void setFeeds(Collection<Feed> feeds) { this.feeds = feeds; }
  | 
  | }

The table is SOURCE_USER is created correctly, users and sources are also stored correctly! The function getUsers or getSources works fine if some data are inserted manually in the SOURCE_USER table, but if I perform a setUsers nothing is inserted in that table.

Here's the code of a session bean where I try to insert relationship data:

 @Stateless
  | @Remote(UserSessionFacade.class)
  | @TransactionManagement(TransactionManagementType.CONTAINER)
  | public class UserSessionFacadeBean implements UserSessionFacade {
  |     static Logger logger=Logger.getLogger(UserSessionFacadeBean.class);
  |     @Resource // Injection using annotations
  |     private SessionContext sessionContext;
  |     //@PersistenceContext(type=PersistenceContextType.EXTENDED,unitName="NewsCrawlerPu")
  |     @PersistenceContext//(unitName="NewsCrawlerPu")
  |     private EntityManager manager;
  | 
  |     @TransactionAttribute(TransactionAttributeType.REQUIRED)
  |     public void createSources(UserDTO userDTO) {
  | 	 if (userDTO == null) { logger.error("UserDTO passed is null!");return; }
  |          logger.debug("Adding sources to a user - dto passed is:".concat(userDTO.toString()));
  |          if(userDTO.getId()!=null || userDTO.getNick()!=null ){
  |              User user=null;
  |              if(userDTO.getId()!=null)
  |                   user = manager.find(User.class,userDTO.getId());
  |              else
  |                   user = findUserByNick(userDTO.getNick());
  |              if(user==null){
  | 	          logger.error("User not found in Db..");
  | 	          //Abort if user does not exist
  | 	          sessionContext.setRollbackOnly();
  | 	     }
  | 	     else{
  | 		  logger.trace("User found in db");
  |                   SourceDTO[] s=userDTO.getSources();
  | 	          Collection<User> list;
  | 		  Object o=null;
  |                   int length;
  |                   if(s!=null && (length=s.length)!=0){
  |                      for (int i = 0; i < length; i++) {
  | 			logger.trace("for cicle: search for "+s.getUrl());
  |                         Source src = null;
  | 			Query q=manager.createNamedQuery("Source.findByUrl");
  | 			logger.trace("Creating namedQuery...");
  | 			try{
  | 			    o=q.setParameter("url",s.getUrl()).getSingleResult();
  | 			}catch(NoResultException e){ 
  | 				logger.warn("Source "+s.getUrl()+" not found!");
  | 				o=null;
  | 			}catch(NonUniqueResultException e){ 
  | 				logger.error("No unique result found!");
  | 				o=null;
  | 			}catch(Exception e){ 
  | 				logger.error("Wrong query: MUST be a SELECT!");
  | 				o=null;
  | 		     	}
  |                         if(o!=null){
  | 			   src=(Source)o;
  | 		           logger.debug("Source already present in Db: ");
  | 		           logger.debug("checking if user already hold it");	
  |                            Collection <User>coll = src.getUsers();
  |                            Iterator<User> iter = coll.iterator();
  |                            boolean found = false;
  |                            while (iter.hasNext() && found==false) {
  |                                User u = iter.next();
  |      			       logger.trace("User: "+u.getUserId()+", "+u.getName());
  | 			       if (u.getUserId()==user.getUserId()) 
  |                                    found = true;
  |                            }
  |                            list = new ArrayList(coll);
  |                            if (!found) {
  |                                logger.debug("Register user to that Source");
  |                                list.add(user);
  | 			       src.setUsers(list);
  | 			       manager.merge(src);
  | 			       manager.refresh(src);
  |                            } else {
  |                                logger.debug("User already registered to that Url");
  |                            }
  | 			}else{
  |                            logger.debug("New Source (not found in Db): adding user to it");
  | 			   src=SourceAssembler.createSource(s);
  |                            list = new ArrayList<User>();
  |                            list.add(user);
  | 			   src.setUsers(list);
  | 			   manager.persist(src);
  | 			   manager.refresh(src);
  | 			}
  |                      }
  |                 }else{
  |                      logger.warn("No source to add...Strange!");
  |             	}
  |             }
  |        }else{
  |            logger.error("Missing user id in the passed DTO or id not valid!");
  |        }
  |     }
  | .....
  | .....
  | 

Any suggest?

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

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



More information about the jboss-user mailing list