[EJB 3.0] - ManyToMany relationship do not work properly
by fla83tn
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;
| //(a)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
18 years, 8 months
[JBoss Seam] - Re: need help using DataModelSelectionIndex
by asookazian
"Kragoth" wrote : As far as I know or at least as far as I can tell, you cannot have a DataModelSelectionIndex and a DataModelSelection on the same DataModel.
|
| You need to choose, do you want the index or the object.
|
| There really is no point in having the DataModelSelection if you have the index as you can get the selected object using the index.
|
| So up to you, if you need the index then do your lookup with the index value to return the selected object.
|
| Hope that makes sense.
|
| for example.
|
| You wrote:
|
| | @DataModel(value="myAuditList")
| | private List myAuditList;
| |
| | @DataModelSelection(value="myAuditList")
| | private Object[] myAuditListSelection;
| |
| | @DataModelSelectionIndex(value="myAuditListSelection")
| | //this is the row number of the underlying collection
| | private int currentRowNum;
| |
|
|
| Change it to:
|
| | @DataModel(value="myAuditList")
| | private List myAuditList;
| |
| | private Object[] myAuditListSelection;
| |
| | @DataModelSelectionIndex(value="myAuditListSelection")
| | //this is the row number of the underlying collection
| | private int currentRowNum;
| |
| | public Object[] getMyAuditListSelection() {
| | return myAuditList.get(currentRowNum);
| | }
| |
|
|
| That should work.....however I havn't tested this so dont' just copy and paste, but that is the general idea ok.
ok, thx. this makes sense to me. I'll try this. I'd say that the Seam doc needs to be clearer on this as there is no example of DataModelSelectionIndex in the Seam distro... thx.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4106476#4106476
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4106476
18 years, 8 months