通过未标记为层叠PERSIST的关系找到了一个新对象 [英] a new object was found through a relationship that was not marked cascade PERSIST

查看:93
本文介绍了通过未标记为层叠PERSIST的关系找到了一个新对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试获取ArticleHeaderField之间的@OneToMany关系时,我可能映射得不太正确,结果是:

In trying to get a @OneToMany relationship between Article and HeaderField I probably have the mapping not quite right, resulting in:

init:
Deleting: /home/thufir/NetBeansProjects/USENET/build/built-jar.properties
deps-jar:
Updating property file: /home/thufir/NetBeansProjects/USENET/build/built-jar.properties
compile:
run:
DEBUG: nntp: newsrc loading /home/thufir/.newsrc
DEBUG: nntp: newsrc load: 1 groups in 31ms
[EL Info]: 2012-07-31 02:05:05.677--ServerSession(8979162)--EclipseLink, version: Eclipse Persistence Services - 2.3.0.v20110604-r9504
[EL Info]: 2012-07-31 02:05:06.778--ServerSession(8979162)--file:/home/thufir/NetBeansProjects/USENET/build/classes/_USENETPU login successful
[EL Warning]: 2012-07-31 02:05:06.903--ServerSession(8979162)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'usenet.HEADERFIELD' doesn't exist
Error Code: 1146
Call: ALTER TABLE HEADERFIELD DROP FOREIGN KEY FK_HEADERFIELD_ARTICLE_ID
Query: DataModifyQuery(sql="ALTER TABLE HEADERFIELD DROP FOREIGN KEY FK_HEADERFIELD_ARTICLE_ID")
[EL Warning]: 2012-07-31 02:05:06.916--ServerSession(8979162)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'ARTICLE'
Error Code: 1051
Call: DROP TABLE ARTICLE
Query: DataModifyQuery(sql="DROP TABLE ARTICLE")
[EL Warning]: 2012-07-31 02:05:07.033--ServerSession(8979162)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'NEWSGROUP'
Error Code: 1051
Call: DROP TABLE NEWSGROUP
Query: DataModifyQuery(sql="DROP TABLE NEWSGROUP")
[EL Warning]: 2012-07-31 02:05:07.122--ServerSession(8979162)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'HEADERFIELD'
Error Code: 1051
Call: DROP TABLE HEADERFIELD
Query: DataModifyQuery(sql="DROP TABLE HEADERFIELD")
[EL Warning]: 2012-07-31 02:05:08.921--UnitOfWork(26970615)--java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: null.
Jul 31, 2012 2:05:08 AM net.bounceme.dur.usenet.driver.Main main
SEVERE: null
javax.persistence.RollbackException: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: null.
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
    at net.bounceme.dur.usenet.driver.Main.persistArticle(Main.java:67)
    at net.bounceme.dur.usenet.driver.Main.<init>(Main.java:43)
    at net.bounceme.dur.usenet.driver.Main.main(Main.java:24)
Caused by: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: null.
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.discoverUnregisteredNewObjects(RepeatableWriteUnitOfWork.java:302)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:695)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1482)
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:265)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1135)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
    ... 4 more

[EL Info]: 2012-07-31 02:05:09.332--ServerSession(8979162)--file:/home/thufir/NetBeansProjects/USENET/build/classes/_USENETPU logout successful
BUILD SUCCESSFUL (total time: 9 seconds)

文章:

package net.bounceme.dur.usenet.model;

import java.io.Serializable;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.persistence.*;

@Entity
public class Article implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(Article.class.getName());
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column
    private String subject;
    @OneToMany(mappedBy = "article", cascade = CascadeType.PERSIST)
    private List<HeaderField> headerFields = new ArrayList<>();

    public Article() {
    }

    public Article(Message message) {
        try {
            subject = message.getSubject();
            Enumeration e = message.getAllHeaders();

            while (e.hasMoreElements()) {
                Header header = (Header) e.nextElement();
                @SuppressWarnings("unchecked")
                SimpleEntry nameValue = new SimpleEntry(header.getName(), header.getValue());
                HeaderField headerField = new HeaderField(nameValue);
                headerFields.add(headerField);
            }
        } catch (MessagingException ex) {
            Logger.getLogger(Article.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public Long getId() {
        return id;
    }

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

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Article)) {
            return false;
        }
        Article other = (Article) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return subject;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }
}

HeaderField:

HeaderField:

package net.bounceme.dur.usenet.model;

import java.io.Serializable;
import java.util.AbstractMap.SimpleEntry;
import java.util.logging.Logger;
import javax.persistence.*;

@Entity
public class HeaderField implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(HeaderField.class.getName());
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne
    private Article article = new Article();
    @Column
    private String headerName;
    @Column
    private String headerValue;

    public HeaderField() {
    }

    public HeaderField(SimpleEntry nameValue) {
        headerName = nameValue.getKey().toString();
        headerValue = nameValue.getValue().toString();
    }

    public Long getId() {
        return id;
    }

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

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof HeaderField)) {
            return false;
        }
        HeaderField other = (HeaderField) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "\n\nheaderName\t" + headerName + "\nheaderValue\t" + headerValue;
    }

    public String getHeaderName() {
        return headerName;
    }

    public void setHeaderName(String headerName) {
        this.headerName = headerName;
    }

    public String getHeaderValue() {
        return headerValue;
    }

    public void setHeaderValue(String headerValue) {
        this.headerValue = headerValue;
    }
}

实体已更新,以反映使用CascadeType.PERSIST的建议,这似乎可以修复该特定错误消息.我正在努力生成更有用的日志以跟踪正在发生的事情.

The entities have been updated to reflect suggestion to use CascadeType.PERSIST which, seemingly, would fix that particular error message. I'm working on generating a more useful log to trace what's happening.

推荐答案

您可能要做的是创建了Article的新实例和HeaderField的一些新实例.然后将HeaderField的这些实例与Article关联.

What you had likely done is that you created new instance of Article and and some new instance(s) of HeaderField. These instance(s) of HeaderField were then associated with Article.

之后,尝试持久化文章失败,因为如错误消息所述,它引用了新对象,并且关系未标记为PERSIST.另外,根据您的日志,这些HeaderField实例没有设置 headerName headerValue .

After that trying to persist Article fails, because as error message says, it refers to new objects and relationship is not marked as PERSIST. Additionally according your logs these instances of HeaderField does not have headerName and headerValue set.

您有两个选择:

  1. 还坚持通过em.persist从Article引用的其他实例
  2. 从文章到HeaderFields的级联持久化操作

  1. persist also other instances referenced from Article via em.persist
  2. cascade persist operation from Article to HeaderFields with following

OneToMany(mappedBy = "article", cascade = CascadeType.PERSIST)  
private List<HeaderField> someOrAllHeaderFields = new ArrayList<>();

此外,您不应该删除no-arg构造函数. JPA实现在创建实例时始终调用此构造函数.

Additionally you should not remove no-arg constructor. JPA implementation always calls this constructor when it creates instance.

但是您可以使no-arg构造函数受到保护.在JPA 2.0规范中,这是用以下几个字来告知的:

But you can make no-arg constructor protected. In JPA 2.0 specification this is told wit following words:

实体类必须具有无参数构造函数.实体类可以 还有其他构造函数. no-arg构造函数必须是公共的 或受保护.

The entity class must have a no-arg constructor. The entity class may have other constructors as well. The no-arg constructor must be public or protected.

这篇关于通过未标记为层叠PERSIST的关系找到了一个新对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆