web-dev-qa-db-ja.com

カスケードPERSISTとマークされていない関係を介して新しいオブジェクトが見つかりました

ArticleHeaderField@OneToMany関係を取得しようとすると、マッピングが正しくない可能性があり、次のようになります。

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:

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を使用する提案を反映するように更新されており、一見、その特定のエラーメッセージを修正します。私は、何が起こっているのかを追跡するためにより有用なログを生成することに取り組んでいます。

32
Thufir

おそらく行ったことは、Articleの新しいインスタンスとHeaderFieldのいくつかの新しいインスタンスを作成したことです。次に、HeaderFieldのこれらのインスタンスは記事に関連付けられました。

エラーメッセージにあるように、新しいオブジェクトを参照し、関係がPERSISTとしてマークされていないため、Articleを永続化しようとすると失敗します。さらに、ログによると、これらのHeaderFieldのインスタンスにはheaderNameおよびheaderValueが設定されていません。

次の2つのオプションがあります。

  1. em.persistを介してArticleから参照される他のインスタンスも保持します
  2. 以下のようにArticleからHeaderFieldsへのカスケード永続操作

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

また、引数なしのコンストラクタを削除しないでください。 JPA実装は、インスタンスを作成するときに常にこのコンストラクターを呼び出します。

ただし、引数なしのコンストラクタを保護することはできます。 JPA 2.0仕様では、これは次の言葉で伝えられます。

エンティティクラスには引数なしのコンストラクタが必要です。エンティティクラスには、他のコンストラクタもあります。引数なしのコンストラクタは、パブリックまたは保護されている必要があります。

54
Mikko Maunu

カスケード属性を削除し、それは私のために働いた:

OneToMany(mappedBy = "article")  
private List<HeaderField> someOrAllHeaderFields = new ArrayList<>();
0
kuma

関係にCascadeType.ALLを追加するだけです

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