Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
javax.persistence.PersistenceException:org.hibernate.persistentObject异常:错误_Java_Hibernate_Jpa_Entitymanager - Fatal编程技术网

javax.persistence.PersistenceException:org.hibernate.persistentObject异常:错误

javax.persistence.PersistenceException:org.hibernate.persistentObject异常:错误,java,hibernate,jpa,entitymanager,Java,Hibernate,Jpa,Entitymanager,我在JPA项目中有2个实体: 一个类别和一个问题。因此,每个类别都有一个问题列表,每个问题都是一个类别的一部分(一对一关系)。我通过两个实体中的set/add方法管理双向关系: 问题: @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "Qcategory") private Category category; public void setCategory(Category category) { this.cate

我在JPA项目中有2个实体:

一个类别和一个问题。因此,每个类别都有一个问题列表,每个问题都是一个类别的一部分(一对一关系)。我通过两个实体中的set/add方法管理双向关系:

问题:

    @ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "Qcategory")
private Category category;

public void setCategory(Category category) {
 this.category = category;

 if (category != null && !category.getQuestions().contains(this)) {
 category.addQuestion(this);
 }
 }
类别:

@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "category")
private List<Question> questions= new ArrayList<Question>();


 public void addQuestion(Question question) {
 this.questions.add(question);

 if (question.getCategory() != this) {
 question.setCategory(this);
 }

 }
我通过我的存储库将其添加到数据库中(添加方式与下面的问题addOrUpdate类似)

然后我创建一个问题

Question question1 = new Question();
我把问题的类别设为1类

question.setCategory = category1;
在此之后,我还尝试通过调用下面的addOrUpdate方法将问题持久化到db。然后我得到一个错误:

....:javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: jpa.entities.Category
我使用的存储库方法如下:

@Override
public boolean addOrUpdate(Question question) {
    EntityManagerFactory emf = JPARepositoryFactory
            .getEntityManagerFactory();
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();

    Question tempQuestion = null;
    try {
        if (question.getId() != null) {
            tempQuestion = em.find(Question.class,
                    question.getId());
        }

        if (tempQuestion == null) {
            em.persist(question);
        } else {

            tempQuestion .setCategory(question.getCategory());
            ... (other setters)
            tempQuestion = em.merge(question);
        }
    } catch (Exception e) {
        ....logging...      }
    tx.commit();
    em.close();
    emf.close();
    return true;
}

任何建议都是非常受欢迎的。

在持久化或合并之前,您必须做的是在每个问题中设置类别引用。

[注意:这可能不是直接的答案,只是一些观察]

  • 使用每个方法调用初始化
    EntityManagerFactory
    显然不是一个好的做法。相反,应该在应用程序启动期间创建一次

  • 您正在将
    类别
    传递到
    addOrUpdate
    ,该类别是另一个持久性上下文的一部分,在该持久性上下文中,它不处于托管状态

  • 您的关系中有什么
    cascade=MERGE
    /
    cascade=PERSIST
    cascade=ALL

  • 可能,您可以在当前操作中再次按id获取
    类别
    ,并在
    问题
    中进行设置,然后再继续

  • 来自文档:

    双向关系必须遵循这些规则

    • 双向关系的反向端必须通过使用@OneToOne的mappedBy元素引用其所属端, @OneToMany或@ManyToMany注释。mappedBy元素指定 实体中的属性或字段,它是 关系
    • 多对一双向关系的多方不能定义mappedBy元素。多方总是拥有方 关系的一部分
    • 对于一对一的双向关系,拥有方对应于包含相应外键的方
    • 对于多对多双向关系,任何一方都可能是拥有方


    因此,只允许对实体调用persist一次。该错误意味着您已经对传入的问题对象调用了persist,但您在另一个事务中调用了persist。如果要将问题对象重新附加到持久性上下文,则需要调用merge或从数据库重新加载它。

    是否对类别调用过persist/merge?您正在为
    tempQuestion
    设置值,但是merging
    Question
    或这只是一个输入错误。@Pace不是直接调用的,我只将关系放在类别上。但我意识到我也将这个问题添加到了分类列表中。但我使用的是CascadeType。所有在实体上有关系的人。所以我相信他会这么做。@NayanWadekar不是打字错误。。。我想我用得对吗?@NayanWadekar我相信这是一种与独立实体合作的方式?!但我在写作时是这样做的:question.setCategory=category1?我在帖子中添加了双向设置。我相信我这样做是正确的,我的关系中有Cascade=CascadeType.ALL(见问题顶部的关系)。我相信我遵守了这种关系的规则。如果您看到我的addOrUpdate方法,我如何再次获取id?@DarthBlueRay它类似于您通过EntityManager获取
    tempQuestion
    ,类似于
    em.find(Question.class,category.getId())
    &然后在
    Question
    中设置它。可以使用单事务传播尝试当前代码。创建类别并将其持久化,然后将其设置为问题并持久化。可以相应地更改持久化/合并操作。我将代码更改为:tempCategory=em.find(Category.class,question.getCategory().getId());tempFeedbackVraag.setCategory(tempCategory);如果这就是你的意思。我也犯了同样的错误。我这样做是错误的。首先,我创建了一个新的类别,即我所坚持的类别。然后我创建一个新问题。然后我将这个类别设置为问题(set),然后尝试保持这个类别。在这种情况下,问题本身是新的(必须持久化),但属性类别有一个指向已准备就绪的持久化类别(因此是分离的对象)的链接。当添加我遇到的新问题时,我不会合并。在持久化之前,我将获取它并尝试设置它。我尝试获取类别,如:tempCategory=em.find(category.class,question.getCategory().getId());问题.集合类别(临时类别);em.persist(问题);我仍然得到相同的错误。我首先创建一个类别并将其保存到数据库(persist)。之后,我创建了一个问题,并将question.setCategory设置为我创建的类别。然后,我尝试将这个新问题保存到db(参考allready激励类别),我将关系的两端保持在正确的状态。我相信这是处理这些关系的“正常”方式。你在另一个中创建一个需要的对象,然后在我创建另一个之前选择它。啊。但是你对你的问题有一个明确的答案。这意味着它将对已经被持久化的类别调用persist,从而调用消息。从问题对象的类别字段中删除持久化级联。这似乎可以做到这一点。我需要加入什么样的级联?我将其更改为Cascade.MERGE,但我需要评估这是否正确。如果在同一事务中创建所有对象,则只希望Cascade持久化。一个典型的例子是有几个行项目的订单。如果要创建订单和所有
    @Override
    public boolean addOrUpdate(Question question) {
        EntityManagerFactory emf = JPARepositoryFactory
                .getEntityManagerFactory();
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
    
        Question tempQuestion = null;
        try {
            if (question.getId() != null) {
                tempQuestion = em.find(Question.class,
                        question.getId());
            }
    
            if (tempQuestion == null) {
                em.persist(question);
            } else {
    
                tempQuestion .setCategory(question.getCategory());
                ... (other setters)
                tempQuestion = em.merge(question);
            }
        } catch (Exception e) {
            ....logging...      }
        tx.commit();
        em.close();
        emf.close();
        return true;
    }