【问题标题】:Hibernate Bidirectional relationshipsHibernate 双向关系
【发布时间】:2014-08-23 12:48:50
【问题描述】:

hibernate中建立双向关系@OneToMany的正确方法是什么?

我有 3 个表 useraccount、category 和 item。在我的项目表中,它包含用户帐户和类别的外键。如果我建立单向,它会在项目类中使用这样的代码进行编译:

@ManyToOne
@JoinColumn(name="cat_id")
public Category getCategory() { return category;    }
public void setCategory(Category category) {this.category = category; }
private Category category;

@ManyToOne
@JoinColumn(name="user_id")
public UserAccount getItemOwner() { return itemOwner;   }
public void setItemOwner(UserAccount itemOwner) {   this.itemOwner = itemOwner; }
private UserAccount itemOwner;

但是当我尝试通过在用户帐户和类别中添加这些映射来定义双向时:

@OneToMany(mappedBy="USERACCOUNTS", targetEntity=Item.class, cascade=CascadeType.ALL)
public Set<Item> getOwnedItems() {  return ownedItems;  }
public void setOwnedItems(Set<Item> ownedItems) {   this.ownedItems = ownedItems;   }
private Set<Item> ownedItems;

@OneToMany(mappedBy="CATEGORIES", targetEntity=Item.class, cascade=CascadeType.ALL)
public Set<Item> getListOfItem() {  return listOfItem;  }
public void setListOfItem(Set<Item> listOfItem) {   this.listOfItem = listOfItem;   }
private Set<Item>listOfItem; 

它给了我这个错误:

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring-servlet.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: com.isad.model.Item.CATEGORIES in com.isad.model.Category.listOfItem
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:684)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: com.isad.model.Item.CATEGORIES in com.isad.model.Category.listOfItem
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:768)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:728)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1695)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1424)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:343)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:431)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:416)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
... 21 more

我查看了文档,但找不到问题的根源。谁能给我建议来解决这个问题。谢谢

【问题讨论】:

    标签: hibernate


    【解决方案1】:

    注解@JoinColumn表示该实体是该关系的所有者(即:对应表有一个列,该列具有引用表的外键),而属性mappedBy表示该实体中的该实体side 是关系的倒数,所有者位于“其他”实体中。

    根据documentation

    由于 多对一 在 JPA 规范中(几乎)总是 双向关系的所有者方,因此一对多关联由 @OneToMany(mappedBy =...)

    @Entity
    public class Troop {
        @OneToMany(mappedBy="troop")
        public Set<Soldier> getSoldiers() {
        ...
    }
    
    @Entity
    public class Soldier {
        @ManyToOne
        @JoinColumn(name="troop_fk")
        public Troop getTroop() {
        ...
    } 
    

    部队通过部队属性与士兵具有双向的一对多关系。您不必(不得)在 mappedBy 端定义任何物理映射。

    要映射一个双向的一对多,一对多的一方作为拥有方,您必须删除 mappedBy 元素并将多设置为一 @JoinColumn 为可插入和可更新为假。此解决方案未优化,会产生一些额外的 UPDATE 语句。

    @Entity
    public class Troop {
        @OneToMany
        @JoinColumn(name="troop_fk") //we need to duplicate the physical information
        public Set<Soldier> getSoldiers() {
        ...
    }
    
    @Entity
    public class Soldier {
        @ManyToOne
        @JoinColumn(name="troop_fk", insertable=false, updatable=false)
        public Troop getTroop() {
        ...
    }
    

    【讨论】:

      【解决方案2】:

      @OneToMany 的所有“mappedBy”都是错误的。它的值应该是对方的属性名,尝试如下配置:

      @OneToMany(mappedBy="itemOwner", cascade=CascadeType.ALL)
      public Set<Item> getOwnedItems() {  return ownedItems;  }
      

      @OneToMany(mappedBy="category", cascade=CascadeType.ALL)
      public Set<Item> getListOfItem() {  return listOfItem;  }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-09
        • 1970-01-01
        • 1970-01-01
        • 2018-01-13
        • 1970-01-01
        • 2016-07-26
        • 2012-03-27
        • 2021-05-14
        相关资源
        最近更新 更多