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
Hibernate onetomany mapping
提问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
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.
- 您的关联是双向的,您需要使用
mappedBy
“一个”端的属性(或者您将获得两个单向关联)来定义“拥有”拥有方(持有外国的一方)关系的字段键,即一对多中的多方)。 - 该
@JoinColumn
注释应在持有端只,而不是双方进行定义。 - 如果您使用的是 Hibernate 的 JPA 2.0 兼容版本(即 Hibernate 3.5+),则更喜欢
@OrderColumn
Hibernate 特定的标准注释@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
资源
- Hibernate Core Documentation
- JPA wiki book
- Hibernate 核心文档
- JPA 维基书
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
@JoinColumn
annotation 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 @Column
annotation upon your Id
fields, in case the name of the actual column is not id
.
此外,您@Column
的Id
字段上缺少注释,以防实际列的名称不是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{}