繁体   English   中英

Hibernate onetomany映射

[英]Hibernate onetomany mapping

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

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

因此,一个项目可以有多个应用程序,但一个应用程序只属于一个项目。

我按如下方式构建它们:

Project.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

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...]
     }

...但不幸的是,我得到了一个我无法处理的例外:

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$1.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$1.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)

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


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

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

谢谢Pascal

您的映射中有几个要修复的问题。

  • 你的关联是双向的,你需要在“一”方面使用mappedBy属性(或者你得到的是两个单向关联)来定义“拥有”拥有方(持有方的一方)关系的字段。外键,即一对多的多方面)。
  • @JoinColumn注释应仅在拥有@JoinColumn ,而不是双方定义。
  • 如果您使用的是兼容JPA 2.0的Hibernate版本(即Hibernate 3.5+),则更喜欢Hibernate特定的@IndexColumn的标准@OrderColumn注释
  • 我不确定为什么你将@JoinColumn定义为完全只读的@JoinColumn updatable = false, insertable = false, nullable=false ,这听起来不合适。

所以你的映射成为(假设你正在使用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
}

@Entity
public class Application {

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

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

    // getters, setters
 }

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

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

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

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

资源

参考

  • JPA 1.0规范
    • 第2.1.8.2节“双向ManyToOne / OneToMany关系”
    • 第9.1.24节“OneToMany注释”
    • 第9.1.22节“ManyToOne注释”
  • JPA 2.0规范
    • 第11.1.39节“OrderColumn注释”

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

而且,你已经描述了如下的东西,

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

它完全没有任何意义。 这实际上意味着你不想更新它,既不想插入它,也不想要它。

此外,如果实际列的名称不是id ,则在Id字段上缺少@Column注释。

实体

@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{}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM