a new object was found through a relationship that was not marked cascade PERSIST
===

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
    Deleted 2 out of date files in 0 seconds
    Compiling 2 source files to /home/thufir/NetBeansProjects/USENET/build/classes
    warning: Supported source version 'RELEASE_6' from annotation processor 'org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor' less than -source '1.7'
    Note: Creating non-static metadata factory ...
    Note: Found Option : eclipselink.canonicalmodel.use_static_factory, with value: false
    Note: Optional file was not found: META-INF/orm.xml continuing with generation.
    Note: Optional file was not found: META-INF/eclipselink-orm.xml continuing with generation.
    Note: Found Option : eclipselink.canonicalmodel.use_static_factory, with value: false
    Note: Optional file was not found: META-INF/orm.xml continuing with generation.
    Note: Optional file was not found: META-INF/eclipselink-orm.xml continuing with generation.
    warning: The following options were not recognized by any processor: '[eclipselink.canonicalmodel.use_static_factory]'
    1 warning
    Copying 1 file to /home/thufir/NetBeansProjects/USENET/build/classes
    compile:
    run:
    DEBUG: nntp: newsrc loading /home/thufir/.newsrc
    DEBUG: nntp: newsrc load: 1 groups in 15ms
    [EL Info]: 2012-07-31 01:18:49.562--ServerSession(14003694)--EclipseLink, version: Eclipse Persistence Services - 2.3.0.v20110604-r9504
    [EL Info]: 2012-07-31 01:18:50.789--ServerSession(14003694)--file:/home/thufir/NetBeansProjects/USENET/build/classes/_USENETPU login successful
    [EL Warning]: 2012-07-31 01:18:50.941--ServerSession(14003694)--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 01:18:50.955--ServerSession(14003694)--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 01:18:51.043--ServerSession(14003694)--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 01:18:51.122--ServerSession(14003694)--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 01:18:54.114--UnitOfWork(20157822)--java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: 
    headerName null
    headerValuenull.
    Jul 31, 2012 1:18:54 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: 
    headerName null
    headerValuenull.
    	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: 
    headerName null
    headerValuenull.
    	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
    
    BUILD SUCCESSFUL (total time: 18 seconds)



Article:


    package net.bounceme.dur.usenet.model;
    
    import java.io.Serializable;
    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.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.AUTO)
        private Long id;
        @Column
        private String subject;
        @OneToMany(mappedBy = "article")
        private List<HeaderField> someOrAllHeaderFields = new ArrayList<>();
    
        public Article() {
        }
    
        public Article(Message message) {
            try {
                subject = message.getSubject();
                Enumeration e = message.getAllHeaders();
                HeaderField headerFieldForThisArticle = new HeaderField(e);
                someOrAllHeaderFields.add(headerFieldForThisArticle);
    } 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.Enumeration;
    import java.util.logging.Logger;
    import javax.mail.Header;
    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.AUTO)
        private Long id;
        @ManyToOne
        private Article article = new Article();
        @Column
        private String headerName;
        @Column
        private String headerValue;
    
        public HeaderField() {
        }
    
        public HeaderField(Enumeration e) {
            while (e.hasMoreElements()) {
                Header h = (Header) e.nextElement();
                LOG.fine(h.getName());
            }
        }
    
        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 "\nheaderName " + headerName + "\nheaderValue" + 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;
        }
    }



This is related to a [previous][1] question, which I believe to have correctly implemented the mapping, but perhaps not.

A small matter, but I would almost want to remove the no-args constructor for `HeaderField` as that should always take an `Enumeration`.  Hmm, actually, that's not correct.  As it stands now, `HeaderField` should only have primitive fields, no collections, and is only a name-value pair.

In any event, I'll still ask the question:  what's wrong with the relationship?


  [1]: http://stackoverflow.com/questions/11718459/onetomany-mappedby-maps-to