Hibernate onetomany映射 [英] Hibernate onetomany mapping
问题描述
有两个类:
- Project(Parent)
- Application(Child)
所以一个项目可以有多个应用程序,但一个应用程序只属于一个项目。
我构建它们如下:
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)
列表<应用程序> applications = new ArrayList< Application>();
[获取和设置方法...]
}
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)
私人项目项目;
[获取和设置方法...]
}
...但不幸的是,我得到了一个我无法处理的异常:
javax.servlet.ServletException:org.hibernate .PropertyValueException:not-null属性引用null或瞬态值:.... 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)
根本原因
javax.faces.el.EvaluationException:org.hibernate.PropertyValueException:not -null属性引用null或瞬态值:.... 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 .serv冰(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)
根本原因
org.hibernate.PropertyValueException :not-null属性引用空值或瞬态值:.... common.entities.Application._applicationsBackref
org.hibernate.engine.Nullability.checkNullability(Nullability.java:95)
org.hibernate .event.def.AbstractSaveEventListener.performS aveOrReplicate AbstractSaveEventListener.java:
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'没有默认值
谢谢帕斯卡尔
您的映射中有几件事需要解决。
- 您的关联是双向的,您需要使用
mappedBy
属性(或者你会得到的是两个单向关联)来定义拥有关系的字段(拥有外键的那一面,即许多方面都是一对多的)。 -
@JoinColumn
注释只能在拥有者一方定义,而不能同时定义如果您使用的是Hibernate(即Hibernate 3.5+)的JPA 2.0兼容版本,则更喜欢标准的@OrderColumn
注释。 的Hiberna特定的 - 我不确定要理解为什么定义
@JoinColumn
完全只读,并且updatable = false,insertable = false,nullable = false
,这听起来不合适。
@IndexColumn
所以你的映射会变成(假设你使用的是JPA 2.0):
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)
私人项目项目;
// getters,setters
}
关联,是双向的,不要忘记在创建对象图时设置链接的两端:
Project p = new项目();
Application a = new Application();
a.setProject(p);
p.getApplications()。add(a);
em.persist(p);
但我实际上建议在您的实体中创建链接管理方法来设置链接的两侧,例如
@Entity
public class Project {
...
public void addToApplications(应用程序应用程序){
this.applications.add(app);
app.setProject(this);
}
...
}
资源
- Hibernate核心文档
- JPA wiki book
- OneToMany关系示例和ManyToOne注释
- JPA 1.0规范
- 第2.1.8.2节双向ManyToOne / OneToMany关系
- 第9.1.24节OneToMany Annotation
- 第9.1.22节ManyToOne批注
- 第2.1.8.2节双向ManyToOne / OneToMany关系
- JPA 2.0规范
- 第11.1.39节OrderColumn注解
参考文献
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
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...] }
...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$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)
Where is my mistake? I mean there is nothing null. Only on project side
When I remove @JoinColumn on owning side an exception occures:
java.sql.SQLException: Field 'project_id' doesn't have a default value
Thank you Pascal
解决方案There are several things to fix in your mapping.
- Your association is bidirectional, you need to use the
mappedBy
attribute 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
@JoinColumn
annotation 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
@OrderColumn
annotation of the Hibernate specific@IndexColumn
- I'm not sure to understand why you defined the
@JoinColumn
as totally read-only withupdatable = false, insertable = false, nullable=false
, this doesn't sound appropriate.
So your mappings become (assuming you're using 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
- Hibernate Core Documentation
- JPA wiki book
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"
这篇关于Hibernate onetomany映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!