2012-01-05 92 views
0

我有这2类:更新实体与许多一对多的关系

@Entity 
public class Student extends User { 
    ... 
    @ManyToMany(mappedBy = "members", fetch = FetchType.EAGER) 
    private Set<Group> groups; 
    ... 
    public void addGroup(Group group) { 
     groups.add(group); 
    } 
} 


@Entity 
@Table(name = "Group") 
public class Group implements Serializable { 
    ...  
    @ManyToMany(fetch = FetchType.EAGER) 
    @JoinTable(name = "member_of") 
    private Set<Student> members; 
    ...  
    public void addMember(Student student) { 
     members.add(student); 
    } 
} 

这是管理他们的关系的会话bean:

@Stateless 
public class StudentManager extends AcademicManager implements StudentManagerRemote { 
    ... 
    @Override 
    public void requestAnswer(long requestID, RequestAnswer answer) { 
     Request request = entityManager.find(Request.class, requestID); 
     if(answer == RequestAnswer.YES) { 
      Student student = request.getStudent(); 
      Group group = request.getGroup(); 
      group.addMember(student); 
      student.addGroup(group); 
      entityManager.flush(); 
      entityManager.clear(); 
     } 
    } 
    ... 
} 

它不更新数据库。为什么?我为其他关系做同样的事情,但这是我唯一的ManyToMany。
我也试过查询,但没有奏效。

编辑:我编辑了像Mr.J4mes建议的代码,但它仍然不起作用。
此外:为什么.flush()和.clear()没有必要?

+0

你的实体中是否有equals和hashCode方法?如果是这样,给他们看。同时显示getMembers()和getGroups()的代码。代码对我来说看起来很不错(除了清除和清除调用,这是没有用的)。 – 2012-01-05 22:39:54

+0

你确定条件'if(answer == RequestAnswer.YES)'评估为真吗?与问题无关:看起来你也不需要在条件失败的情况下找到'Request'。这些方法不需要被调用,因为'requestAnswer'方法在方法完成时提交的事务中运行。 – 2012-01-05 22:59:09

+0

@βнɛƨнǤʋяʋиɢ该方法比这更复杂,它执行其他控件,我需要这个请求,因为无论答案如何,我都必须在方法结尾删除它(我刚刚发布了不起作用的部分。以前的零件不会修改ojbect,只需检查一些条件)。关于这种情况,我百分百确定它是真的。 – Simon 2012-01-05 23:06:01

回答

0

当您致电group.getMembers()时,您只需从Group实体获取包含StudentSet的副本。因此,当您更新它时,Group实体中的Set不会更新。你有两个选择:

  1. 获取SetGroup和更新之后重新设置:

    Set<Student> members = group.getMembers(); 
    members.add(student); 
    group.setMembers(members); 
    
  2. 添加的方法addStudentGroup实体&的方法addGroupStudent实体内部调用在您的requestAnswer方法中。这将是这样的:

    @Entity 
    public class Group implements Serializable { 
        private Set<Student> members; 
    
        public void addMember(Student student) { 
         this.members.add(student); 
        } 
    } 
    
    @Stateless 
    public class StudentManager extends AcademicManager implements StudentManagerRemote { 
        @PersistenceContext 
        private EntityManager em; 
        ... 
        @Override 
        public void requestAnswer(long requestID, RequestAnswer answer) { 
         Request request = entityManager.find(Request.class, requestID); 
         if(answer == RequestAnswer.YES) { 
          Student student = request.getStudent(); 
          Group group = request.getGroup(); 
          group.addMember(student); 
          student.addGroup(group); 
         } 
        } 
        ... 
    } 
    

再说了,你并不真的需要调用em.flush()em.cancel()

+1

为什么他会得到一份副本?只有当getter明确地创建一个集合的副本时(如返回新的HashSet (this.members);),这才是真实的。如果没有复制,则返回该集合的引用,并且OP的代码应该没问题。这就是为什么我要求他提供获得者的代码。 – 2012-01-05 23:09:23

+0

@JBNizet嗯。我想不出任何其他解释这种行为。我曾经喜欢过他,即使“Set ”的获得者只有这一行:'return students;',它也不起作用。我非常好奇:P – 2012-01-05 23:16:48

+0

好吧,你所建议的addStudent方法与getStudents()。add(...)完全一样,如果副本不是由getter创建的,所以应该没有区别。 – 2012-01-05 23:21:34