java 休眠onetomany映射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3657197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:53:00  来源:igfitidea点击:

Hibernate onetomany mapping

javahibernate

提问by Sven

I try to map a relation for the first time. I have found a lot of ways to go.

我第一次尝试映射关系。我找到了很多方法。

There are two classes: - Project (Parent) - Application (Child)

有两个类: - 项目(父) - 应用(子)

So one project can have several applications, but one application belongs to just one project..

所以一个项目可以有多个应用程序,但一个应用程序只属于一个项目..

I constructed them as follows:

我按如下方式构建它们:

Project.java

项目.java

 import javax.persistence.CascadeType;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.OneToMany;

    @Entity
    public class Project {

     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private int id;
        @OneToMany(cascade = CascadeType.ALL)
        @JoinColumn(name = "project_id", nullable=false)
        @org.hibernate.annotations.IndexColumn(name = "project_index")
        List<Application> applications = new ArrayList<Application>();

        [get and set methods...]
        }

Application.java

应用程序.java

import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.ManyToOne;

    @Entity
    public class Application {

         @Id
         @GeneratedValue(strategy = GenerationType.IDENTITY)
         private int id;

            @ManyToOne
            @JoinColumn(name = "project_id", updatable = false, insertable = false, nullable=false)
            private Project project;

        [get and set methods...]
     }

...but, unfortunately I got an exception I can not deal with:

...但是,不幸的是我遇到了一个我无法处理的异常:

javax.servlet.ServletException: org.hibernate.PropertyValueException: not-null property references a null or transient value: ....common.entities.Application._applicationsBackref
 javax.faces.webapp.FacesServlet.service(FacesServlet.java:321)
 org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:359)
 org.apache.shiro.web.servlet.AbstractShiroFilter.call(AbstractShiroFilter.java:275)
 org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
 org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
 org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:343)
 org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:272)
 org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:83)

root cause

javax.faces.el.EvaluationException: org.hibernate.PropertyValueException: not-null property references a null or transient value: ....common.entities.Application._applicationsBackref
 javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:98)
 com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:98)
 javax.faces.component.UICommand.broadcast(UICommand.java:311)
 javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:781)
 javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1246)
 com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:77)
 com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
 com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
 javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
 org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:359)
 org.apache.shiro.web.servlet.AbstractShiroFilter.call(AbstractShiroFilter.java:275)
 org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
 org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
 org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:343)
 org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:272)
 org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:83)

root cause

org.hibernate.PropertyValueException: not-null property references a null or transient value: ....common.entities.Application._applicationsBackref
 org.hibernate.engine.Nullability.checkNullability(Nullability.java:95)
 org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
 org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
 org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
 org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
 org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
 org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
 org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
 org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)

Where is my mistake? I mean there is nothing null. Only on project side

我的错误在哪里?我的意思是没有什么是空的。仅在项目方



When I remove @JoinColumn on owning side an exception occures:

当我删除拥有方的@JoinColumn 时,发生异常:

java.sql.SQLException: Field 'project_id' doesn't have a default value


Thank you Pascal

谢谢帕斯卡

回答by Pascal Thivent

There are several things to fix in your mapping.

在您的映射中有几件事情需要解决。

  • Your association is bidirectional, you need to use the mappedByattribute on the "One" side (or what you'll get is two unidirectional associations) to define the field that "owns" the relation on the owning side (the side that holds the foreign key i.e. the Many side in a one-to-many).
  • The @JoinColumnannotation should be defined on the owning side only, not both sides.
  • If you are using a JPA 2.0 compliant version of Hibernate (i.e. Hibernate 3.5+), prefer the standard @OrderColumnannotation of the Hibernate specific @IndexColumn
  • I'm not sure to understand why you defined the @JoinColumnas totally read-only with updatable = false, insertable = false, nullable=false, this doesn't sound appropriate.
  • 您的关联是双向的,您需要使用mappedBy“一个”端的属性(或者您将获得两个单向关联)来定义“拥有”拥有方(持有外国的一方)关系的字段键,即一对多中的多方)。
  • @JoinColumn注释应在持有端只,而不是双方进行定义。
  • 如果您使用的是 Hibernate 的 JPA 2.0 兼容版本(即 Hibernate 3.5+),则更喜欢@OrderColumnHibernate 特定的标准注释@IndexColumn
  • 我不确定您为什么将 定义@JoinColumn为完全只读updatable = false, insertable = false, nullable=false,这听起来不合适。

So your mappings become (assuming you're using JPA 2.0):

所以你的映射变成了(假设你使用的是 JPA 2.0):

@Entity
public class Project {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy="project")
    @OrderColumn(name = "project_index")
    List<Application> applications = new ArrayList<Application>();

    // getters, setters
}

And

@Entity
public class Application {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @ManyToOne
    @JoinColumn(name = "project_id")
    private Project project;

    // getters, setters
 }

And since your association, is bidirectional, don't forget to set both sides of the link when creating your object graph:

并且由于您的关联是双向的,因此在创建对象图时不要忘记设置链接的两侧:

Project p = new Project();
Application a = new Application();
a.setProject(p);
p.getApplications().add(a);
em.persist(p);

But I would actually recommend to create link management methods in your entities to set both sides of the link, e.g.

但我实际上建议在您的实体中创建链接管理方法来设置链接的两侧,例如

@Entity
public class Project {
    ...
    public void addToApplications(Application app) {
        this.applications.add(app);
        app.setProject(this);
    }
    ...
}

Resources

资源

References

参考

  • JPA 1.0 specification
    • Section 2.1.8.2 "Bidirectional ManyToOne / OneToMany Relationships"
    • Section 9.1.24 "OneToMany Annotation"
    • Section 9.1.22 "ManyToOne Annotation"
  • JPA 2.0 specification
    • Section 11.1.39 "OrderColumn Annotation"
  • JPA 1.0 规范
    • 第 2.1.8.2 节“双向多对一/一对多关系”
    • 第 9.1.24 节“一对多注释”
    • 第 9.1.22 节“多对一注释”
  • JPA 2.0 规范
    • 第 11.1.39 节“OrderColumn 注释”

回答by Adeel Ansari

@JoinColumnannotation is not needed on both sides. In fact, you should only put this on owning side of the relationship.

@JoinColumn两边都不需要注释。事实上,你应该只把它放在关系的拥有方。

Moreover, you have describe the thing as below,

此外,你已经描述了下面的事情,

@JoinColumn(name = "project_id", updatable = false, insertable = false, nullable=false)

@JoinColumn(name = "project_id", updatable = false, insertable = false, nullable=false)

Its totally making no sense. This, acutally, means that you don't want to update it, neither you like to insert it, nor you want it null.

它完全没有意义。这实际上意味着您不想更新它,既不想插入它,也不希望它为空。

Furthermore, you are missing @Columnannotation upon your Idfields, in case the name of the actual column is not id.

此外,您@ColumnId字段上缺少注释,以防实际列的名称不是id

回答by O Henry

Entity

实体

@Table(name="Customer_v1")

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)

public class?Customer implements Serializable{????????????????

??????????????? @Id

??????????????? @Column(name="cust_id")

??????????????? protected int custId;

?------------------------------------------------

@Entity

@DiscriminatorValue(value = "N")

public class NewCustomer extends Customer {}

?

@Entity

@DiscriminatorValue( value="E")

public class ExistingCustomer extends Customer{}