多对多的JPA映射插入,但不会显示子集合 [英] many-to-many JPA mapping inserting but not fething the child collections

查看:111
本文介绍了多对多的JPA映射插入,但不会显示子集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我再次用hibernate触发了一个模块。我在用户和联系人管理的不同方面发布了很多次,我一直在建立。

可悲的是,我真的没有时间去玩,并且在开始使用它之前更好地理解它。对不起,但英语不是我的母语,我更喜欢说法语。再次,我开始用自动的方式编写java代码。我通过阅读书籍来完成所有这些工作,并且没有去上学。有时间限制,很难从头到尾阅读一本书。

我不确定我应该把我的每个代码处理一个问题在这里,从我从其他论坛学到的是张贴必要和简明。

所以在我的用户模型中,我有UserAccount类,它拥有诸如名称,首选项等的详细信息,AccountSession和Phone。
我的联系人管理模型有联系人和组。

UserAccount与个人资料具有一对一的关联,一对多与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)
私人UserProfile配置文件;

@OneToMany(targetEntity = ContactImpl.class,cascade = {CascadeType.ALL},mappedBy =userAccount)
@ org.hibernate.annotations.Cascade(value = org.hibernate。 annotations.CascadeType.DELETE_ORPHAN)
私人设定<联络人> contacts = new HashSet< Contact>();

@OneToMany(targetEntity = GroupImpl.class,cascade = {CascadeType.ALL},mappedBy =userAccount)
@ org.hibernate.annotations.Cascade(value = org.hibernate。 annotations.CascadeType.DELETE_ORPHAN)
private Set< Group> groups = new HashSet< Group>();
.......

// 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< Contact> 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< Group> groups = new HashSet< Group>();
....

//组$ b的辅助方法$ b $ public void addContact(Contact contact){
try {
this.getContacts()。增加联系人);
contact.getGroups()。add(this);
} catch(Exception e){

}

}

//组$ b的辅助方法public void removeContact (联系人联系人){
contact.getGroups()。remove(contact);
this.getContacts()。remove(contact);


$ b $ //联系人
的辅助方法public void addGroup(Group group){
try {
this.getGroups() 。新增(基);
group.getContacts()。add(this);
} catch(Exception e){
e.printStackTrace();



//组$ b的辅助方法public void removeGroup(Group group){
try {

。group.getContacts()除去(本);
this.getGroups()。remove(group);
} catch(Exception e){
e.printStackTrace();




$ p $ UserAccount setter来自Contact.All多对一具有相同的
/ **
* @param userAccount userAccount设置
* /
public void setUserAccount(UserAccount userAccount){
this .userAccount = userAccount;
}



我想通过其UserAccount表中唯一字段的email字段来提取UserAccount。

In UserAccountDAO我调用以获取UserAccount的方法是getUserAccountByEmail这里below.So我期望此方法加载UserAccount的所有子集合,即它的联系人集合,组collection.I希望它以这样的方式,当UserAccount加载联系人集合中的每个联系人对象都有其所属集团集合的引用(如果有),反之亦然。

  public UserAccount getUserAccountByEmail(字符串电子邮件){
//尝试{
logger.info(inside getUserAccountByEmail);
logger.debug(email);
Session session =(Session)this.getDBSession()。getSession();
UserAccount user =(UserAccount)session.createCriteria(this.getPersistentClass())
.setFetchMode(contacts,FetchMode.SELECT)//最近添加了
.setFetchMode(groups, FetchMode.SELECT)//最近添加了
.add(Restrictions.eq(email,email))
.uniqueResult();
logger.debug(user);
返回用户;
//} catch(NonUniqueResultException ne){
// logger.debug(异常发生:getUserAccountByEmail返回多个结果,ne);
//返回null;
// catch(HibernateException he){
// logger.debug(Exception Occured:Persistence or JDBC exception in method getUserAccountByEmail,he);
//返回null;
//} catch(Exception e){
// logger.debug(Exception Occured:Exception in method getUserAccountByEmail,e);
//返回null;
//

由于在任何联系人和组之前必须有UserAccount,我的单元测试时测试保存一个联系对象,必须有一个现有的组我做这个按顺序

a 创建userAccount对象ua。

b 创建组对象g1;

c 创建联系人对象c1;

d .addGroup(g1);

e c1.setUserAccount(ua);

f c1.addGroup(g1);

g uaDao.save(ua); //因为级联而节省组的成本

h cDao.save(c1);


大多数情况下,我使用hibernate的session.get()来通过hibernate生成的id来获取c1,并执行所有实际工作的断言。 p>

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

1。我该怎么做才能解决这个问题?

2。 辅助方法工作正常,但它在父方(我在测试中做)。我一直在想的是做c1.setUserAccount(ua);足以在UserAccount和contact之间建立强有力的关系。大多数情况下,我不会出现将userAccount与联系人保存在一起的情况,但尚未设置在两侧设置关联并且在UserAccount中不会调用的帮助器方法我保存了一个特定的userAccount的联系人,所以我对此有点困惑,并且怀疑关联的设置是为什么某些东西不能正常工作的一部分,然后调用session.get(UserAccount.class,ua.getID( ))我认为是我想要的,我想getUserAccountByEmail做同样的。

3。 ChssPly76认为映射必须重写。所以我愿意让我们通过这个指导我。我真的需要知道正确的方法来做到这一点,因为我们不能从一本好书中倚靠一切。所以我认为我应该改变映射只是告诉我how.and很可能我在做事情错误的方式甚至没有意识到这一点,所以不要忘记我仍然learni ng java本身。大胆的建议和评论,并感谢您阅读本文

解决方案

我同意你的看法,您的父对象与其子集合之间的关联没有得到正确保存。我总是喜欢通过查看数据库中的内容来确定发生了什么。在运行测试之后,你在实际的数据库中看到了什么?



似乎可能发生以下两种情况之一(以UserAccount为例):


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


  2. 子集合中的项目正在保存到数据库,但没有与父对象的所需关联,在这种情况下,您将看到子项的行,但连接列(即'userAccount'将为空)。这可能是由于未在子对象上设置userAccount()属性造成的。

  3. 我遇到了你所描述的问题。首先看看数据库中的内容,看看是否会让你走得更远。


    i've hit a block once again with hibernate.I've posted numerous times on different aspects of the user and contact management that i've been building.

    The sad thing is that i didn't really have the time to play with it and understand it better before actually starting working with it. Sorry but English is not my native language, i rather speak french. And again i've started coding in java in an autodidact way.i'm doing all of this by reading books and haven't gone to school for it. with time constraints it's hard to read a book from beginning to the end.
    I'm not sure i should put every of my codes dealing with an issue here and from what i've learned from other forum is to post just the necessary and being concise.

    So in my User model i have UserAccount class, Profile that holds details like name, preferences etc , AccountSession and Phone. my contact management model have Contact and Group.

    UserAccount has one-to-one association with Profile, one-to-many with AccountSession,contact and group, all bidirectional.the one-to-many association with phone is unidirectional because contact also has and unidirectional with Phone.

    Contact has a bidirectional many-o-many with group and one-to-many with phone that i said earlier. Group also has a many-to-many bedirectional with contact.

    here are the mappings

    // 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<Contact> contacts = new HashSet<Contact>();
    
    @OneToMany(targetEntity=GroupImpl.class, cascade={CascadeType.ALL}, mappedBy="userAccount")
    @org.hibernate.annotations.Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Set<Group> groups = new HashSet<Group>();
    .......
    
    //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<Contact> contacts = new HashSet<Contact>();
    
    //Contact
     ....
     @ManyToOne(targetEntity=UserAccountImpl.class)
    @JoinColumn(name="USER_ACCOUNT_ID",nullable=false)
    private UserAccount userAccount;
    
    @ManyToMany(targetEntity=GroupImpl.class, mappedBy="contacts")
    private Set<Group> groups=new HashSet<Group>();
    ....
    
    // 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();
        }
    }
    

    //UserAccount setter from Contact.All the children with many-to-one have the same /** * @param userAccount the userAccount to set */ public void setUserAccount(UserAccount userAccount) { this.userAccount = userAccount; }

    I'ld like to pull the UserAccount by its email field which is an unique field in the UserAccount table.
    In the UserAccountDAO the method i call to get the UserAccount is getUserAccountByEmail here below.So i expect this method to load all the children collections of the UserAccount namely its Contact collection, group collection.I want it in such a way that when UserAccount is loaded with Contacts collection each of the contact object has its reference with its belonging groups collection if any etc and vice versa.

     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;
    //       }
    

    Since there has to be an UserAccount before any contact and groups, in my unit test when testing the saving of a contact object for which there must be an existing group i do this in order
    a create userAccount object ua.
    b create group object g1;
    c create contact object c1;
    d ua.addGroup(g1);
    e c1.setUserAccount(ua);
    f c1.addGroup(g1);
    g uaDao.save(ua); // which saves the group because of the cascade
    h cDao.save(c1);

    Most of the time i use the session.get() from hibernate to pull c1 by its it id generated by hibernate and do all the assertions which works actually.

    but in Integration test when i call getUserAccountByEmail with and without the setFetchMode and it returns the right object but then all the children collections are empty. i've tried the JOIN and the SELECT.the query string changes but then the result set is still the same. So this arises some questions :

    1. What should i do to fix this?
    2. the helper method works fine but it's on the parent side(i do it in the test).What i've been wondering about is that doing c1.setUserAccount(ua); is enough to create a strong relationship between UserAccount and contact.most of the time there will not be cases where i save the userAccount with contact but yet the helper method that set the association in both side and which is in UserAccount will not been called before i save the contact for a particular userAccount.So i'm little confused about that and suspecting that setting of the association is part of the why something is not working properly.and then calling session.get(UserAccount.class, ua.getID()) i think goes what i want and i'ld like getUserAccountByEmail to do the same.
    3. ChssPly76 thinks the mapping has to be rewrite.So i'm willing to let you guide me through this.I really need to know the proper way to do this because we can't lean everything from a good book.So i you think i should change the mapping just show me how.and probable i'm doing things the wrong way without even been aware of that so don't forget i'm still learning java itself.THanks for the advise and remarks and thanks for reading this

    解决方案

    I agree with you that it seems likely that the associations between your parent objects and their child collections are not getting persisted properly. I always like to start out by looking at what is in the database to figure out what's going on. After you run your test what do you see in the actual database?

    It seems likely that one of two things is happening (using UserAccount as an example):

    1. The items in the child collection are not getting saved to the database at all, in which case you'll be able to see in the database that there are no records associated with your UserAccount. This could be caused by saving the UserAccount object before you've added the child object to the UserAccount's collection.

    2. The items in the child collection are getting saved to the database, but without the needed association to the parent object, in which case you'll see rows for your child items but the join column (ie 'userAccount' will be null). This could be caused by not setting the userAccount() property on the child object.

    These are the two scenarios that I've run into where I've seen the problem you describe. Start by taking a look at what goes into your database and see if that leads you farther.

    这篇关于多对多的JPA映射插入,但不会显示子集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆