2017-06-06 73 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