[英]Java JPA - save many-to-many structure to DB - error: attempted to assign id from null one-to-one property
I try to save a many-to-many construct into my DB with JPA. 我尝试使用JPA将多对多结构保存到数据库中。 There are Recipes and MealPlans and a MealPlan can have multiple Recipes.
有食谱和膳食计划,并且一个膳食计划可以具有多个食谱。 And a Recipe can be in multiple MealPlans.
一个配方可以在多个MealPlan中。
Classes: Recipe and MealPlan . 课程: Recipe和MealPlan 。
Matching table: MealPlanRecipe consist of a recipe_id
, mealplan_id
and a attribute portions . 匹配表: MealPlanRecipe由
recipe_id
, mealplan_id
和属性部分组成 。
I generate a MealPlan and want to save in the DB, creating an error. 我生成一个MealPlan并想保存在数据库中,从而产生一个错误。 See all below and many thanks in advance!!
请参阅下面的所有内容,并在此先感谢!! Chris
克里斯
-- -
class Recipe: 类食谱:
@Entity(name = "Recipe")
@Table(name = "recipe")
@XmlRootElement
public class Recipe implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 255)
@Column(name = "name")
private String name;
[...]
class MealPlan: MealPlan类:
@Entity(name = "MealPlan")
@Table(name = "mealplan")
@XmlRootElement
public class MealPlan implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 255)
@Column(name = "name")
String name;
@OneToMany(
mappedBy = "mealplan",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<MealPlanRecipe> mealplanrecipe = new ArrayList<>();
[...]
class MealPlanRecipe: MealPlanRecipe类:
@Entity(name = "MealPlanRecipe")
@Table(name = "mealplanrecipe")
@XmlRootElement
public class MealPlanRecipe implements Serializable {
private static final long serialVersionUID = 1L;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("recipeId")
private Recipe recipe;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("mealplanId")
private MealPlan mealplan;
@EmbeddedId
protected MealPlanRecipePK mealplanrecipePK;
@Basic(optional = false)
@NotNull
@Column(name = "portions")
private int portions;
[...]
class MealPlanRecipePK: MealPlanRecipePK类:
public class MealPlanRecipePK implements Serializable {
@Basic(optional = false)
@NotNull
@Column(name = "recipe_id")
private int recipeId;
@Basic(optional = false)
@NotNull
@Column(name = "mealplan_id")
private int mealplanId;
public MealPlanRecipePK() {
}
public MealPlanRecipePK(int recipeId, int mealplanId) {
this.recipeId = recipeId;
this.mealplanId = mealplanId;
}
public int getRecipeId() {
return recipeId;
}
public void setRecipeId(int recipeId) {
this.recipeId = recipeId;
}
public int getMealplanId() {
return mealplanId;
}
public void setMealplanId(int mealplanId) {
this.mealplanId = mealplanId;
}
@Override
public int hashCode() {
int hash = 7;
hash = 67 * hash + this.recipeId;
hash = 67 * hash + this.mealplanId;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final MealPlanRecipePK other = (MealPlanRecipePK) obj;
if (this.recipeId != other.recipeId) {
return false;
}
if (this.mealplanId != other.mealplanId) {
return false;
}
return true;
}
}
Executed code: 执行的代码:
MealPlan tosave;
[here, fill "tosave"-Object: Add Recipes to its ArrayList..]
if(tosave!=null){
this.sql.getEM().getTransaction().begin();
this.sql.getEM().persist(tosave);
this.sql.getEM().getTransaction().commit();
}
Output / error: 输出/错误:
javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [orm.MealPlanRecipe.mealplan]
javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [orm.MealPlanRecipe.mealplan]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1187)
at com.mycompany.meallion.Menu.processRequest(Menu.java:74)
at com.mycompany.meallion.Menu.doGet(Menu.java:103)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [orm.MealPlanRecipe.mealplan]
at org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:98)
at org.hibernate.mapping.Component$ValueGenerationPlan.execute(Component.java:440)
at org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGeneratedValueGenerator.java:121)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:117)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:801)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:794)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:97)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:379)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:319)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:460)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:294)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
atorg.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
EDIT: 编辑:
I put this loop in the Execution code to set all MealPlanRecipe.mealplan attributes: 我将此循环放在执行代码中,以设置所有MealPlanRecipe.mealplan属性:
for(MealPlanRecipe mpr : tosave.GetMealPlanRecipes()){
mpr.setMealplan(tosave);
}
Now, I get this Error: 现在,我得到这个错误:
javax.persistence.PersistenceException:
org.hibernate.PropertyAccessException: could not set a field value by
reflection setter of orm.MealPlanRecipePK.mealplanId
[...]
Caused by: java.lang.NullPointerException
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:57)
at sun.reflect.UnsafeIntegerFieldAccessorImpl.set(UnsafeIntegerFieldAccessorImpl.java:75)
at java.lang.reflect.Field.set(Field.java:764)
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:122)
Thanks to crizzis and xerx593: 感谢crizzis和xerx593:
Apparently, within the MealPlan, the MealPlan.mealplanrecipe
was not initialized AND within each MealPlan.mealplanrecipe
the PK object had to be initialized, too. 显然,MealPlan内,该
MealPlan.mealplanrecipe
没有初始化,并且每个内MealPlan.mealplanrecipe
的PK对象必须被初始化了。 I forgot this, though Java is doing it.. I added: 我忘记了这一点,尽管Java正在这样做。
public void setDefaultPKObject(){
this.mealplanrecipePK = new MealPlanRecipePK();
}
and run this for every element in MealPlan.mealplanrecipe
并针对
MealPlan.mealplanrecipe
每个元素运行此MealPlan.mealplanrecipe
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.