簡體   English   中英

在jpa 2.1中使用ManyToMany時的分離實體

[英]detached entity when using ManyToMany in jpa 2.1

我正在創建一個應用程序,我在RecipeIngredients之間有一個ManyToMany關系,但是當我嘗試使用JPA 2.1在RecipeIngredient插入新行時,我得到了:

引起:javax.persistence.PersistenceException:org.hibernate.PersistentObjectException:傳遞給persist的分離實體。

這是我的實體:`

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@CrossCheck
public class Ingredient implements ValidEntity {

static final String PREFIX = "com.architech.sales.ingredient.entity.";
public static final String FIND_ALL = PREFIX + "FIND_ALL";
public static final String FIND_BY_ID = PREFIX + "FIND_BY_ID";

@Id
@GeneratedValue
private long id;

@NotNull
private String label;
private String description;

// added just to reply to @Maciej-Kowalski
@OneToMany(targetEntity = RecetteIngredient.class, mappedBy = "ingredient")
private List<RecetteIngredient> recetteIngredients;

@Version
private long version;
// Getter / Setter

}

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@CrossCheck
public class Recette implements ValidEntity{

static final String PREFIX = "sales.recette.entity.Recette.";
public static final String FIND_ALL = PREFIX + "FIND_ALL";
public static final String FIND_BY_ID = PREFIX + "FIND_BY_ID";

@Id
@GeneratedValue
private long id;

@Size(min = 1, max = 256)
private String label;
private String description;

@OneToMany(targetEntity = RecetteIngredient.class, mappedBy = "recette")
private List<RecetteIngredient> recetteIngredients;

@Version
private long version;

// Getter/Setter
}
`

`

@Entity
@IdClass(RecetteIngredientPK.class)
public class RecetteIngredient implements Serializable{

@Id
private long id;
private double qte;

@Id
@ManyToOne(targetEntity = Ingredient.class)
private Ingredient ingredient;

@Id
@ManyToOne(targetEntity = Recette.class)
private Recette recette;

// Getter/Setter
}
`

和我的持久單位

<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="prod" transaction-type="JTA"> <properties> <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/> <!--<property name="hibernate.enable_lazy_load_no_trans" value="true" />--> </properties> </persistence-unit> </persistence>

這是堆棧跟蹤:

`

    Caused by: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.architech.sales.ingredient.entity.Ingredient
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1171)
    at org.jboss.as.jpa.container.AbstractEntityManager.merge(AbstractEntityManager.java:565)
    at com.architech.sales.recette_ingredient.boundary.RecetteIngredientManager.save(RecetteIngredientManager.java:47)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
`

這就是我試圖持久化RecetteIngredient的方法:

`
@Stateless
@Interceptors(BoundaryLogger.class)
public class RecetteIngredientManager {

@PersistenceContext
EntityManager em;

public RecetteIngredient findById(long id) {
    return this.em.find(RecetteIngredient.class, id);
}

public void delete(long id) {
    try {
        RecetteIngredient reference = this.em.getReference(RecetteIngredient.class, id);
        this.em.remove(reference);
    } catch (EntityNotFoundException e) {
        //we want to remove it...
    }
}

public RecetteIngredient save(RecetteIngredient recetteIngredient) {
    return this.em.merge(recetteIngredient);
}

}

`

在鏈接類中,在@ManyToOne映射上添加merge cascade選項:

@Entity
@IdClass(RecetteIngredientPK.class)
public class RecetteIngredient implements Serializable{

@Id
private long id;
private double qte;

@Id
@ManyToOne(targetEntity = Ingredient.class, cascade = CascadeType.MERGE)
private Ingredient ingredient;

@Id
@ManyToOne(targetEntity = Recette.class, cascade = CascadeType.MERGE)
private Recette recette;

這將建議PersistenceContext同時合並Ingredient和Recette實體,如果它們恰好在當時被分離。

如果您不允許更改注釋,則必須在持久化鏈接表之前手動保留/合並Ingredient和Recette實體:

public RecetteIngredient save(RecetteIngredient recette) {
  this.em.merge(recette.getIngredient());
  this.em.merge(recette.getRecette());

  return this.em.merge(recette);
}

當然這是一種解決方法,第一種方法肯定更優雅,更可取。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM