Java Hibernate-无法添加或更新子行

Java Hibernate-无法添加或更新子行,java,spring,hibernate,jpa,Java,Spring,Hibernate,Jpa,我遇到了一个关于Hibernate的问题,我在其他任何地方都找不到答案。我已经尝试了这里关于StackOverflow的建议,但是我看不出这里的代码与工作示例有什么不同。每当我尝试运行集成测试(如下所列)时,它都会失败,并显示“外键约束失败”消息(有关错误和相关文件的详细信息如下) 我做错了什么 错误消息: org.hibernate.exception.ConstraintViolationException: could not insert: [net.redacted.miseenpla

我遇到了一个关于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
交互集成测试

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();
    }