2012-01-05 78 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

相關問題