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.propertiesdeps-jar:Updating property file: /home/thufir/NetBeansProjects/USENET/build/built-jar.propertiescompile:run:DEBUG: nntp: newsrc loading /home/thufir/.newsrcDEBUG: 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.DatabaseExceptionInternal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'usenet.HEADERFIELD' doesn't existError Code: 1146Call: ALTER TABLE HEADERFIELD DROP FOREIGN KEY FK_HEADERFIELD_ARTICLE_IDQuery: 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.DatabaseExceptionInternal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'ARTICLE'Error Code: 1051Call: DROP TABLE ARTICLEQuery: 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.DatabaseExceptionInternal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'NEWSGROUP'Error Code: 1051Call: DROP TABLE NEWSGROUPQuery: 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.DatabaseExceptionInternal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'HEADERFIELD'Error Code: 1051Call: DROP TABLE HEADERFIELDQuery: 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 mainSEVERE: nulljavax.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 successfulBUILD 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.*;@Entitypublic 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; }}标题字段:package net.bounceme.dur.usenet.model;import java.io.Serializable;import java.util.AbstractMap.SimpleEntry;import java.util.logging.Logger;import javax.persistence.*;@Entitypublic 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 实例然后与文章相关联.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.您有两个选择:还通过 em.persist 保留文章中引用的其他实例从文章到 HeaderFields 的级联持久化操作persist also other instances referenced from Article via em.persistcascade persist operation from Article to HeaderFields with followingOneToMany(mappedBy = "article", cascade = CascadeType.PERSIST)private List<HeaderField> someOrAllHeaderFields = new ArrayList<>();此外,您不应删除无参数构造函数.JPA 实现在创建实例时总是调用这个构造函数.Additionally you should not remove no-arg constructor. JPA implementation always calls this constructor when it creates instance.但是您可以保护无参数构造函数.在 JPA 2.0 规范中,这是用以下文字说明的:But you can make no-arg constructor protected. In JPA 2.0 specification this is told wit following words:实体类必须有一个无参数构造函数.实体类可以还有其他构造函数.无参数构造函数必须是公共的或受保护. 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 的关系发现了新对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 09-03 08:24