Java Hibernate-无法添加或更新子行
我遇到了一个关于Hibernate的问题,我在其他任何地方都找不到答案。我已经尝试了这里关于StackOverflow的建议,但是我看不出这里的代码与工作示例有什么不同。每当我尝试运行集成测试(如下所列)时,它都会失败,并显示“外键约束失败”消息(有关错误和相关文件的详细信息如下) 我做错了什么 错误消息:Java Hibernate-无法添加或更新子行,java,spring,hibernate,jpa,Java,Spring,Hibernate,Jpa,我遇到了一个关于Hibernate的问题,我在其他任何地方都找不到答案。我已经尝试了这里关于StackOverflow的建议,但是我看不出这里的代码与工作示例有什么不同。每当我尝试运行集成测试(如下所列)时,它都会失败,并显示“外键约束失败”消息(有关错误和相关文件的详细信息如下) 我做错了什么 错误消息: org.hibernate.exception.ConstraintViolationException: could not insert: [net.redacted.miseenpla
org.hibernate.exception.ConstraintViolationException: could not insert: [net.redacted.miseenplace.domain.IngredientInstance]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:64)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2345)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2852)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:320)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:713)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:701)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:697)
at net.redacted.miseenplace.service.impl.HibernateDao.add(HibernateDao.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy22.add(Unknown Source)
at net.redacted.miseenplace.integration.RecipeIntegrationTest.recipeIntegrationTest(RecipeIntegrationTest.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`miseenplace`.`ingredient_instance`, CONSTRAINT `FK15EDCF432DFAC9AF` FOREIGN KEY (`id`) REFERENCES `recipe` (`recipeId`))
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
at com.mysql.jdbc.Util.getInstance(Util.java:381)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3491)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2019)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1937)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1922)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:94)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)
... 57 more
交互集成测试
package net.redacted.miseenplace.integration;
import org.hibernate.mapping.Set;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import net.redacted.miseenplace.DomainAwareBase;
import net.redacted.miseenplace.domain.Ingredient;
import net.redacted.miseenplace.domain.IngredientInstance;
import net.redacted.miseenplace.domain.Recipe;
import net.redacted.miseenplace.service.dao.IngredientDao;
import net.redacted.miseenplace.service.dao.IngredientInstanceDao;
import net.redacted.miseenplace.service.dao.RecipeDao;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import static org.junit.Assert.*;
@ContextConfiguration(locations = "/persistence-beans.xml")
public class RecipeIntegrationTest extends DomainAwareBase{
@Autowired
private IngredientDao ingredientDao;
@Autowired
private IngredientInstanceDao ingredientInstanceDao;
@Autowired
private RecipeDao recipeDao;
@Test
public void recipeIntegrationTest(){
Recipe recipe = new Recipe("Integration Test Recipe");
//Add Instructions
LinkedHashSet<String> instructions = new LinkedHashSet<String>();
instructions.add("This is an instruction.");
recipe.setRecipeSteps(instructions);
recipeDao.add(recipe);
Ingredient cookingOil = new Ingredient("Cooking Oil");
ingredientDao.add(cookingOil);
//Create IngredientInstances
IngredientInstance iCookingOil = new IngredientInstance("1/8 cup", cookingOil);
iCookingOil.setRecipe(recipe);
ingredientInstanceDao.add(iCookingOil);
//Add IngredientInstances to recipe
HashSet<IngredientInstance> inginst = new HashSet<IngredientInstance>();
//inginst.add(iCookingOil);
recipe.setRecipeIngredients(inginst);
recipeDao.update(recipe);
recipe.prettyPrint();
}
}
您正在持久化一个不在持久化上下文中的对象
Recipe
。
这意味着您正在尝试添加没有持久配方的Ingredian
尝试执行以下操作:
@Test
public void recipeIntegrationTest(){
Recipe recipe = new Recipe("Integration Test Recipe");
//Add Instructions
LinkedHashSet<String> instructions = new LinkedHashSet<String>();
instructions.add("This is an instruction.");
recipe.setRecipeSteps(instructions);
//get the persisted recipe
recipe = recipeDao.add(recipe);
Ingredient cookingOil = new Ingredient("Cooking Oil");
ingredientDao.add(cookingOil);
//Create IngredientInstances
IngredientInstance iCookingOil = new IngredientInstance("1/8 cup", cookingOil);
iCookingOil.setRecipe(recipe);
ingredientInstanceDao.add(iCookingOil);
//Add IngredientInstances to recipe
HashSet<IngredientInstance> inginst = new HashSet<IngredientInstance>();
//inginst.add(iCookingOil);
//recipe.setRecipeIngredients(inginst); --> you don't need to do this unless //you have new persisted ingredians
// recipeDao.update(recipe); update is not needed either
recipe.prettyPrint();
}
@测试
公共无效recipeIntegrationTest(){
配方=新配方(“集成测试配方”);
//添加说明
LinkedHashSet指令=新建LinkedHashSet();
说明。添加(“这是一项说明”);
配方。设置配方步骤(说明);
//获取持久化的配方
配方=recipeDao.add(配方);
配料烹饪油=新配料(“食用油”);
添加(烹饪油);
//创建InCreditInstances
IngredientInstance ICOOKIGOIL=新的IngredientInstance(“1/8杯”,烹饪油);
iCookingOil.setRecipe(配方);
IngreditInstanceDao.add(iCookingOil);
//向配方中添加IngreditInstances
HashSet ingist=新的HashSet();
//在列表中添加(ICookongoil);
//recipe.setRecipeIngElements(InList);-->除非//有新的持久化ingredians,否则不需要执行此操作
//recipeDao.update(配方);也不需要更新
配方。预打印();
}
package net.redacted.miseenplace.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import net.redacted.miseenplace.domain.Ingredient;
import net.redacted.miseenplace.domain.Recipe;
@Entity
@Table(name = "ingredient_instance")
public class IngredientInstance {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long ingredientInstanceId;
@ManyToOne
@JoinColumn(name="recipeId")
private Recipe recipe;
private String quantity;
@ManyToOne
@JoinColumn(name="id")
private Ingredient ingredient;
protected IngredientInstance() {
}
public IngredientInstance(String quantity, Ingredient ingredient) {
this.quantity = quantity;
this.ingredient = ingredient;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IngredientInstance other = (IngredientInstance) obj;
if (ingredient == null) {
if (other.ingredient != null)
return false;
} else if (!ingredient.equals(other.ingredient))
return false;
if (quantity == null) {
if (other.quantity != null)
return false;
} else if (!quantity.equals(other.quantity))
return false;
return true;
}
public Ingredient getIngredient() {
return ingredient;
}
public long getIngredientInstanceId() {
return ingredientInstanceId;
}
public String getQuantity() {
return quantity;
}
public Recipe getRecipe() {
return recipe;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((ingredient == null) ? 0 : ingredient.hashCode());
result = prime * result
+ ((quantity == null) ? 0 : quantity.hashCode());
return result;
}
public void setIngredient(Ingredient ingredient) {
this.ingredient = ingredient;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
public void setRecipe(Recipe recipe) {
this.recipe = recipe;
}
@Override
public String toString() {
return "IngredientInstance [id=" + ingredientInstanceId + ", quantity=" + quantity
+ ", ingredient=" + ingredient + "]";
}
}
@Test
public void recipeIntegrationTest(){
Recipe recipe = new Recipe("Integration Test Recipe");
//Add Instructions
LinkedHashSet<String> instructions = new LinkedHashSet<String>();
instructions.add("This is an instruction.");
recipe.setRecipeSteps(instructions);
//get the persisted recipe
recipe = recipeDao.add(recipe);
Ingredient cookingOil = new Ingredient("Cooking Oil");
ingredientDao.add(cookingOil);
//Create IngredientInstances
IngredientInstance iCookingOil = new IngredientInstance("1/8 cup", cookingOil);
iCookingOil.setRecipe(recipe);
ingredientInstanceDao.add(iCookingOil);
//Add IngredientInstances to recipe
HashSet<IngredientInstance> inginst = new HashSet<IngredientInstance>();
//inginst.add(iCookingOil);
//recipe.setRecipeIngredients(inginst); --> you don't need to do this unless //you have new persisted ingredians
// recipeDao.update(recipe); update is not needed either
recipe.prettyPrint();
}