我遇到了Hibernate的一个问题,我无法找到其他任何地方的答案。我在StackOverflow上尝试了这里的建议,但我看不出我的代码在这里与工作示例有什么不同。每当我尝试运行我的集成测试(下面列出)时,它都会失败并显示外键约束失败消息(错误和相关文件的完整详细信息如下)。
我做错了什么?
错误讯息:
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
RecipeIntegrationTest
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();
}
}
配方
package net.redacted.miseenplace.domain;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
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;
import javax.persistence.Table;
@Entity
@Table(name = "recipe")
public class Recipe {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long recipeId;
private String recipeName;
private LinkedHashSet<String> recipeSteps;
@OneToMany(mappedBy="recipe")
private Set<IngredientInstance> recipeIngredients;
protected Recipe() {
}
public Recipe(String recipeName) {
this.recipeName = recipeName;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Recipe other = (Recipe) obj;
if (recipeIngredients == null) {
if (other.recipeIngredients != null)
return false;
} else if (!recipeIngredients.equals(other.recipeIngredients))
return false;
if (recipeName == null) {
if (other.recipeName != null)
return false;
} else if (!recipeName.equals(other.recipeName))
return false;
if (recipeSteps == null) {
if (other.recipeSteps != null)
return false;
} else if (!recipeSteps.equals(other.recipeSteps))
return false;
return true;
}
public long getId() {
return recipeId;
}
public HashSet<IngredientInstance> getRecipeIngredients() {
return (HashSet<IngredientInstance>)recipeIngredients;
}
public String getRecipeName() {
return recipeName;
}
public LinkedHashSet<String> getRecipeSteps() {
return recipeSteps;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime
* result
+ ((recipeIngredients == null) ? 0 : recipeIngredients
.hashCode());
result = prime * result
+ ((recipeName == null) ? 0 : recipeName.hashCode());
result = prime * result
+ ((recipeSteps == null) ? 0 : recipeSteps.hashCode());
return result;
}
public void setRecipeIngredients(
HashSet<IngredientInstance> recipeIngredients) {
this.recipeIngredients = recipeIngredients;
}
public void setRecipeName(String recipeName) {
this.recipeName = recipeName;
}
public void setRecipeSteps(LinkedHashSet<String> recipeSteps) {
this.recipeSteps = recipeSteps;
}
@Override
public String toString() {
return "Recipe [id=" + recipeId + ", recipeName=" + recipeName
+ ", recipeSteps=" + recipeSteps + ", recipeIngredients="
+ recipeIngredients + "]";
}
public void prettyPrint() {
//Header with title
System.out.println("");
System.out.println("=========================================================");
System.out.println(this.recipeId + " : " + this.recipeName);
System.out.println("---------------------------------------------------------");
System.out.println("Ingredients");
for(IngredientInstance ii : this.recipeIngredients) {
System.out.println("\t" + ii.getQuantity() + "\t" + ii.getIngredient().getIngredientName() + "\t" + "(" + ii.getIngredient().getIngredientId() + ")");
}
System.out.println("");
System.out.println("---------------------------------------------------------");
System.out.println("Steps:");
for(String ss : this.recipeSteps) {
System.out.println("\t" + ss);
}
System.out.println("");
System.out.println("=========================================================");
}
}
IngredientInstance
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 + "]";
}
}
答案 0 :(得分:0)
您持久存在一个不在持久化上下文中的对象Recipe
。
这意味着你正在尝试添加没有持久配方的配方
尝试做以下事情:
@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();
}