2017-06-06 74 views
0

这真让我费解。无法在休眠中保存ManyToMany关系

我有以下类别:

Ingredient.java

@Entity 
@Table(name = "INGREDIENTS", uniqueConstraints = 
{@UniqueConstraint(columnNames = "NAME")}) 
public class Ingredient implements Serializable{ 

@Id 
@GeneratedValue 
@Column(name = "ingredient_id") 
private Long id; 

@Column(nullable = false, name = "name") 
private String name; 

@Column(nullable = false, name = "name") 
private Long calories; 

public Ingredient() { 
} 

public Ingredient(String name, Long calories) { 
    this.name = name; 
    this.calories = calories; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public Long getCalories() { 
    return calories; 
} 

public void setCalories(Long calories) { 
    this.calories = calories; 
} 

public Long getId(){ 
    return this.id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

}

Meal.java

@Entity 
@Table(name = "MEALS") 
public class Meal implements Serializable { 

@ManyToOne 
private User user; 

@Id 
@GeneratedValue 
@Column(name = "meal_id") 
private Long id; 

@ElementCollection(targetClass = Ingredient.class) 
private Set<Ingredient> ingredients = new HashSet<>(0); 

//More fields and constructors 

@ManyToMany(targetEntity = Ingredient.class, cascade = CascadeType.ALL) 
@JoinTable(name = "ingredient_meal", joinColumns = {@JoinColumn(name = "meal_id")}, inverseJoinColumns = {@JoinColumn(name = "ingredient_id")}) 
public List<Ingredient> getIngredients() { 
    return ingredients; 
} 

public void setIngredients(List<Ingredient> ingredients) { 
    this.ingredients = ingredients; 
} 


public Long getId(){ 
    return this.id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

这是我坚持的实体代码:

SessionFactory sessionFactory = 
entityManagerFactory.unwrap(SessionFactory.class); 

Session session = sessionFactory.openSession(); 
session.beginTransaction(); 

/***/ 
Meal coolMeal = new Meal(user, new Date(115, 0, 8), new Time(19, 0, 0), "8 - 
Moules Frites", 1000L); 
coolMeal.getIngredients().add(new Ingredient("Fish2", 100L)); 
     session.persist(coolMeal); 
    try{ 
     session.getTransaction().commit(); 
    }catch(Throwable e){ 
     e.printStackTrace(); 
     throw e; 
    } 
    session.close(); 

但我不断收到此异常:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: calories.tracker.app.model.Ingredient 
at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:294) 
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:537) 
at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:165) 
at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:899) 
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1308) 
at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:67) 
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463) 
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349) 
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350) 
at 

但是如果我坚持的对象以这种方式:

Ingredient i1 = new Ingredient("Potatoes2", 100L); 
    session.persist(i1); 
    Meal coolMeal = new Meal(user, new Date(115, 0, 8), new Time(19, 0, 0), 
    "8 - Moules Frites", 1000L); 
    coolMeal.getIngredients().add(i1); 

它工作正常,为什么?一切都与here完全一样。

+0

首先,要保证访问类型的一致性,即将所有注释放置在任何字段或属性中,而不是混合。那我们再来看看。 – ram

+0

宣称'成份'属于'Set'类型,但getter返回'List'? –

+0

对不起,尝试使用列表而不是Set如示例 – Santi

回答

1

您声明了ingredients字段的两个映射。
一个领域,另一个在吸气:

@ElementCollection(targetClass = Ingredient.class) 
private Set<Ingredient> ingredients = new HashSet<>(0);  
....   
@ManyToMany(targetEntity = Ingredient.class, cascade = CascadeType.ALL) 
@JoinTable(name = "ingredient_meal", joinColumns = {@JoinColumn(name = "meal_id")}, inverseJoinColumns = {@JoinColumn(name = "ingredient_id")}) 
public List<Ingredient> getIngredients() { 
    return ingredients; 
} 

您应该删除注释的字段:

@ElementCollection(targetClass = Ingredient.class) 

@ElementCollection被设计成非实体类映射而Ingredient是一个实体:

据的Javadoc:

Eleme ntCollection

定义了一个基本类型或嵌入类

0

,你必须使用@OneToMany(mappedBy = "Ord", cascade = CascadeType.ALL, fetch = FetchType.LAZY),通过你的实体名称替换Ord的实例的集合。

+0

那样尝试复制/粘贴这不是OneToMany,而是ManyToMany单向 – Santi