2014-06-30 32 views
0

我遇到了Hibernate的一个问题,我无法在其他任何地方找到答案。我已经在StackOverflow上尝试了这里的建议,但是我看不到我的代码在工作示例中有所不同。无论何时我尝试运行我的集成测试(下面列出),它都会失败,出现外键约束失败消息(有关错误和相关文件的完整详细信息)。Java休眠 - 无法添加或更新子行

我在做什么错?

错误消息:

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

您正在坚持一个不在持续上下文中的对象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(); 
    } 
相关问题