多对多JPA映射插入但不会影响子集合

我已经用hibernate再次打了一个块。我已经多次发布了用户和联系人管理的不同方面,我一直在构建。

可悲的是,在真正开始使用它之前,我没有真正有时间玩它并更好地理解它。 对不起,英语不是我的母语,我更喜欢讲法语。 我再次开始以自学成分的方式在java中编码。我通过阅读书籍来完成所有这些工作并且没有去上学。 由于时间限制,从头到尾都很难读一本书。
我不确定我是否应该把我的每个代码都放在这里处理问题,而且从我从其他论坛学到的东西就是发布必要的和简洁的。

所以在我的用户模型中我有UserAccount类,Profile包含名称,首选项等详细信息,AccountSession和Phone。 我的联系人管理模式有联系人和小组。

UserAccount与Profile一对一关联,与AccountSession一对多,联系人和组,所有双向。与电话的一对多关联是单向的,因为联系人也具有单向和电话。

联系人有一个双向多对多组合和一对多用手机,我之前说过。 集团还有多对多的接触方式。

这是映射

// UserAccount ...... @OneToOne(targetEntity=UserProfileImpl.class,cascade={CascadeType.ALL}) @org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @JoinColumn(name="USER_PROFILE_ID") private UserProfile profile; @OneToMany(targetEntity=ContactImpl.class, cascade={CascadeType.ALL}, mappedBy="userAccount") @org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private Set contacts = new HashSet(); @OneToMany(targetEntity=GroupImpl.class, cascade={CascadeType.ALL}, mappedBy="userAccount") @org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private Set groups = new HashSet(); ....... //Group @ManyToOne(targetEntity=UserAccountImpl.class) @JoinColumn(name="USER_ACCOUNT_ID",nullable=false) private UserAccount userAccount; @ManyToMany(targetEntity=ContactImpl.class,cascade={CascadeType.PERSIST, CascadeType.MERGE}) @JoinTable(name="GROUP_CONTACT_MAP", joinColumns={@JoinColumn(name="GROUP_ID")}, inverseJoinColumns={@JoinColumn(name="CONTACT_ID")}) private Set contacts = new HashSet(); //Contact .... @ManyToOne(targetEntity=UserAccountImpl.class) @JoinColumn(name="USER_ACCOUNT_ID",nullable=false) private UserAccount userAccount; @ManyToMany(targetEntity=GroupImpl.class, mappedBy="contacts") private Set groups=new HashSet(); .... // helper methods from group public void addContact(Contact contact) { try{ this.getContacts().add(contact); contact.getGroups().add(this); }catch(Exception e) { } } //helper method from group public void removeContact(Contact contact) { contact.getGroups().remove(contact); this.getContacts().remove(contact); } //helper method from contact public void addGroup(Group group) { try{ this.getGroups().add(group); group.getContacts().add(this); } catch(Exception e) { e.printStackTrace(); } } //Helper method from group public void removeGroup(Group group){ try{ group.getContacts().remove(this); this.getGroups().remove(group); } catch(Exception e) { e.printStackTrace(); } } 

//来自Contact.All的UserAccount setter所有具有多对一的孩子具有相同的/ ** * @param userAccount userAccount to set * / public void setUserAccount(UserAccount userAccount){this.userAccount = userAccount; }

我想通过其电子邮件字段提取UserAccount,这是UserAccount表中的唯一字段。
在UserAccountDAO中,我调用以获取UserAccount的方法是下面的getUserAccountByEmail。所以我希望这个方法加载UserAccount的所有子集合,即它的Contact集合,集合集合。我希望它以加载UserAccount时的方式加载如果有联系人集合,则每个联系人对象都有其所属的组集合,反之亦然。

  public UserAccount getUserAccountByEmail(String email) { // try { logger.info("inside getUserAccountByEmail"); logger.debug(email); Session session = (Session) this.getDBSession().getSession(); UserAccount user = (UserAccount) session.createCriteria(this.getPersistentClass()) .setFetchMode("contacts", FetchMode.SELECT) //recently added .setFetchMode("groups", FetchMode.SELECT) // recently added .add(Restrictions.eq("email", email)) .uniqueResult(); logger.debug(user); return user; // } catch(NonUniqueResultException ne) { // logger.debug("Exception Occured: getUserAccountByEmail returns more than one result ", ne); // return null; // } catch(HibernateException he){ // logger.debug("Exception Occured: Persistence or JDBC exception in method getUserAccountByEmail ",he); // return null; // }catch(Exception e) { // logger.debug("Exception Occured: Exception in method getUserAccountByEmail", e); // return null; // } 

由于在任何联系人和组之前必须有UserAccount,在我的unit testing中,在测试保存必须有现有组的联系对象时,我按顺序执行此操作
创建userAccount对象ua。
b创建组对象g1;
c创建联系对象c1;
d ua.addGroup(g1);
e c1.setUserAccount(ua);
f c1.addGroup(g1);
g uaDao.save(ua); //由于级联而保存组
h cDao.save(c1);

大多数时候我使用来自hibernate的session.get()通过hibernate生成的id来拉取c1并执行所有实际工作的断言。

但是在Integration测试中,当我使用和不使用setFetchMode调用getUserAccountByEmail时,它返回正确的对象,但是所有子集合都是空的。 我已经尝试了JOIN和SELECT.the查询字符串更改,但结果集仍然是相同的。 所以这引起了一些问题:

1.我该怎么做才能解决这个问题?
2.帮助方法工作正常,但它在父方(我在测试中做)。我一直在想的是做c1.setUserAccount(ua); 足以在UserAccount和contact之间创建一个强大的关系。大部分时间都不会出现我通过联系人保存userAccount的情况,但是在两侧设置关联并且在UserAccount中设置关联的辅助方法之前不会被调用我保存了特定userAccount的联系人。所以我对此感到困惑,并怀疑该关联的设置是为什么某些东西不能正常工作的一部分。然后调用session.get(UserAccount.class,ua.getID( ))我认为我想要的东西,我喜欢getUserAccountByEmail做同样的事情。
3. ChssPly76认为映射必须重写。所以我愿意让你指导我。我真的需要知道这样做的正确方法,因为我们不能从一本好书中倾斜所有东西。所以我你我认为我应该改变映射只是告诉我怎么样。可能我做错事的方式甚至没有意识到这一点所以不要忘记我还在学习java本身。为建议和评论提供意见并感谢阅读这个

我同意你的观点,你的父对象和它们的子集合之间的关联似乎没有得到正确的持久化。 我总是喜欢从查看数据库中的内容来了解​​发生了什么。 运行测试后,您在实际数据库中看到了什么?

看起来可能发生了两件事之一(使用UserAccount作为示例):

  1. 子集合中的项目根本不会保存到数据库中,在这种情况下,您将能够在数据库中看到没有与您的UserAccount关联的记录。 这可能是在将子对象添加到UserAccount的集合之前保存UserAccount对象引起的。

  2. 子集合中的项目将保存到数据库中,但不需要与父对象关联,在这种情况下,您将看到子项目的行,但是连接列(即’userAccount’将为null)。 这可能是因为未在子对象上设置userAccount()属性。

这是我遇到的两个场景,我看到了你描述的问题。 首先来看一下数据库中的内容,看看是否会让您更进一步。