请伙计们咨询
在JPA中保持OneToMany关系时遇到问题,请参见以下示例,
家长呼叫
@Entity
@Table(name="SALES_INVOICES")
public class SalesInvoice {
@Id
@Column(name="INV_ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long invoiceID;
@Column(name="INV_NO", nullable=false)
private long invoiceNumber;
@Column(name="DOC_TYPE")
private String docType;
@Column(name="INV_TOTAL")
private BigDecimal totalInvoice;
@Column(name="NOTES")
private String notes;
@Column(name="STORE_ID")
private int storeID;
@Column(name="INV_DATE")
private Date invoiceDate;
@Column(name="CUST_ID",nullable=true)
private int cusomerID;
@Column(name="OPER_TYPE")
private String operType;
@Column(name="TECH_ID", nullable=true)
private int techID;
@ManyToOne
@PrimaryKeyJoinColumn(name="STORE_ID", referencedColumnName="STORE_ID")
private Store store;
@ManyToOne
@PrimaryKeyJoinColumn(name="CUST_ID", referencedColumnName="CUST_ID")
private Customer customer;
@OneToMany(mappedBy="invoice",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@JoinColumn(name="INV_ID")
private List<InvoiceLine> lines;
@ManyToOne
@PrimaryKeyJoinColumn(name="TECH_ID",referencedColumnName="TECH_ID")
private Technician technician;
/**
* @return the operTypeID
*/
public String getOperType() {
return operType;
}
/**
* @param operTypeID the operTypeID to set
*/
public void setOperType(String operType) {
this.operType = operType;
}
/**
* @return the techID
*/
public int getTechID() {
return techID;
}
/**
* @param techID the techID to set
*/
public void setTechID(int techID) {
this.techID = techID;
}
/**
* @return the lines
*/
public List<InvoiceLine> getLines() {
return lines;
}
/**
* @param lines the lines to set
*/
public void setLines(List<InvoiceLine> lines) {
this.lines = lines;
}
/**
* @return the technician
*/
public Technician getTechnician() {
return technician;
}
/**
* @param technician the technician to set
*/
public void setTechnician(Technician technician) {
this.technician = technician;
}
/**
* @return the cusomerID
*/
public int getCusomerID() {
return cusomerID;
}
/**
* @param cusomerID the cusomerID to set
*/
public void setCusomerID(int cusomerID) {
this.cusomerID = cusomerID;
}
/**
* @return the store
*/
public Store getStore() {
return store;
}
/**
* @param store the store to set
*/
public void setStore(Store store) {
this.store = store;
}
/**
* @return the customer
*/
public Customer getCustomer() {
return customer;
}
/**
* @param customer the customer to set
*/
public void setCustomer(Customer customer) {
this.customer = customer;
}
public SalesInvoice(){}
/**
* @return the invoiceID
*/
public long getInvoiceID() {
return invoiceID;
}
/**
* @param invoiceID the invoiceID to set
*/
public void setInvoiceID(long invoiceID) {
this.invoiceID = invoiceID;
}
/**
* @return the invoiceNumber
*/
public long getInvoiceNumber() {
return invoiceNumber;
}
/**
* @param invoiceNumber the invoiceNumber to set
*/
public void setInvoiceNumber(long invoiceNumber) {
this.invoiceNumber = invoiceNumber;
}
/**
* @return the docType
*/
public String getDocType() {
return docType;
}
/**
* @param docType the docType to set
*/
public void setDocType(String docType) {
this.docType = docType;
}
/**
* @return the totalInvoice
*/
public BigDecimal getTotalInvoice() {
return totalInvoice;
}
/**
* @param totalInvoice the totalInvoice to set
*/
public void setTotalInvoice(BigDecimal totalInvoice) {
this.totalInvoice = totalInvoice;
}
/**
* @return the notes
*/
public String getNotes() {
return notes;
}
/**
* @param notes the notes to set
*/
public void setNotes(String notes) {
this.notes = notes;
}
/**
* @return the storeID
*/
public int getStoreID() {
return storeID;
}
/**
* @param storeID the storeID to set
*/
public void setStoreID(int storeID) {
this.storeID = storeID;
}
/**
* @return the invoiceDate
*/
public Date getInvoiceDate() {
return invoiceDate;
}
/**
* @param invoiceDate the invoiceDate to set
*/
public void setInvoiceDate(Date invoiceDate) {
this.invoiceDate = invoiceDate;
}
}
//////////////////////////////////////////////
HERE IS THE CHILD CLASS....
@Entity
@Table(name="INV_LINES")
public class InvoiceLine {
@Id
@Column(name="LINE_ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long lineID;
@Column(name="INV_ID")
private long invoiceID;
@Column(name="STOCK_ITEM")
private String stockItem;
@Column(name="QTY")
private int quantity;
@Column(name="TOTAL_PRICE")
private BigDecimal totalPrice;
@Column(name="NOTES")
private String notes;
@Column(name="WARRANTY")
private boolean warranted;
@Column(name="DAYS_WARRANTY")
private int warrantyDays;
@ManyToOne
@PrimaryKeyJoinColumn(name="STOCK_ITEM",referencedColumnName="ITEM_ID")
private StockItem item;
@ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@PrimaryKeyJoinColumn(name="INV_ID", referencedColumnName="INV_ID")
private SalesInvoice invoice;
/**
* @return the invoiceID
*/
public long getInvoiceID() {
return invoiceID;
}
/**
* @param invoiceID the invoiceID to set
*/
public void setInvoiceID(long invoiceID) {
this.invoiceID = invoiceID;
}
/**
* @return the invoice
*/
public SalesInvoice getInvoice() {
return invoice;
}
/**
* @param invoice the invoice to set
*/
public void setInvoice(SalesInvoice invoice) {
this.invoice = invoice;
this.invoiceID = invoice.getInvoiceID();
}
public InvoiceLine(){}
/**
* @return the lineID
*/
public long getLineID() {
return lineID;
}
/**
* @param lineID the lineID to set
*/
public void setLineID(long lineID) {
this.lineID = lineID;
}
/**
* @return the stockItem
*/
public String getStockItem() {
return stockItem;
}
/**
* @param stockItem the stockItem to set
*/
public void setStockItem(String stockItem) {
this.stockItem = stockItem;
}
/**
* @return the quantity
*/
public int getQuantity() {
return quantity;
}
/**
* @param quantity the quantity to set
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}
/**
* @return the totalPrice
*/
public BigDecimal getTotalPrice() {
return totalPrice;
}
/**
* @param totalPrice the totalPrice to set
*/
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
/**
* @return the notes
*/
public String getNotes() {
return notes;
}
/**
* @param notes the notes to set
*/
public void setNotes(String notes) {
this.notes = notes;
}
/**
* @return the warranted
*/
public boolean isWarranted() {
return warranted;
}
/**
* @param warranted the warranted to set
*/
public void setWarranted(boolean warranted) {
this.warranted = warranted;
}
/**
* @return the warrantyDays
*/
public int getWarrantyDays() {
return warrantyDays;
}
/**
* @param warrantyDays the warrantyDays to set
*/
public void setWarrantyDays(int warrantyDays) {
this.warrantyDays = warrantyDays;
}
/**
* @return the item
*/
public StockItem getItem() {
return item;
}
/**
* @param item the item to set
*/
public void setItem(StockItem item) {
this.item = item;
}
}
尝试保留SalesInvoice时出现以下错误
问题在这里:
[EL Info]: 2014-11-17 16:42:24.445--ServerSession(314966354)--EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
[EL Warning]: metadata: 2014-11-17 16:42:39.74--ServerSession(314966354)--Reverting the lazy setting on the OneToOne or ManyToOne attribute [invoice] for the entity class [class com.mehwar.model.InvoiceLine] since weaving was not enabled or did not occur.
[EL Info]: connection: 2014-11-17 16:42:39.866--ServerSession(314966354)--file:/C:/Users/Omar/workspace/MehwarBOF/bin/_ss login successful
[EL Warning]: 2014-11-17 16:43:17.85--UnitOfWork(464433398)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: INSERT on table 'INV_LINES' caused a violation of foreign key constraint 'INV_LINES_INV_ID' for key (0). The statement has been rolled back.
Error Code: 20000
Call: INSERT INTO INV_LINES (INV_ID, NOTES, QTY, STOCK_ITEM, TOTAL_PRICE, WARRANTY, DAYS_WARRANTY) VALUES (?, ?, ?, ?, ?, ?, ?)
bind => [7 parameters bound]
Query: InsertObjectQuery(com.mehwar.model.InvoiceLine@28444350)
Exception in thread "AWT-EventQueue-0" javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: INSERT on table 'INV_LINES' caused a violation of foreign key constraint 'INV_LINES_INV_ID' for key (0). The statement has been rolled back.
Error Code: 20000
Call: INSERT INTO INV_LINES (INV_ID, NOTES, QTY, STOCK_ITEM, TOTAL_PRICE, WARRANTY, DAYS_WARRANTY) VALUES (?, ?, ?, ?, ?, ?, ?)
bind => [7 parameters bound]
Query: InsertObjectQuery(com.mehwar.model.InvoiceLine@28444350)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:157)
at com.mehwar.controllers.SalesInvController.actionPerformed(SalesInvController.java:94)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$400(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: INSERT on table 'INV_LINES' caused a violation of foreign key constraint 'INV_LINES_INV_ID' for key (0). The statement has been rolled back.
Error Code: 20000
Call: INSERT INTO INV_LINES (INV_ID, NOTES, QTY, STOCK_ITEM, TOTAL_PRICE, WARRANTY, DAYS_WARRANTY) VALUES (?, ?, ?, ?, ?, ?, ?)
bind => [7 parameters bound]
Query: InsertObjectQuery(com.mehwar.model.InvoiceLine@28444350)
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:900)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:962)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:631)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2002)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:377)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:165)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:180)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:489)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1737)
at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:226)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsForClassWithChangeSet(CommitManager.java:193)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:138)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4207)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
... 37 more
Caused by: java.sql.SQLIntegrityConstraintViolationException: INSERT on table 'INV_LINES' caused a violation of foreign key constraint 'INV_LINES_INV_ID' for key (0). The statement has been rolled back.
at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
at org.apache.derby.client.am.PreparedStatement.executeUpdate(Unknown Source)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:890)
... 69 more
Caused by: org.apache.derby.client.am.SqlException: INSERT on table 'INV_LINES' caused a violation of foreign key constraint 'INV_LINES_INV_ID' for key (0). The statement has been rolled back.
at org.apache.derby.client.am.Statement.completeExecute(Unknown Source)
at org.apache.derby.client.net.NetStatementReply.parseEXCSQLSTTreply(Unknown Source)
at org.apache.derby.client.net.NetStatementReply.readExecute(Unknown Source)
at org.apache.derby.client.net.StatementReply.readExecute(Unknown Source)
at org.apache.derby.client.net.NetPreparedStatement.readExecute_(Unknown Source)
at org.apache.derby.client.am.PreparedStatement.readExecute(Unknown Source)
at org.apache.derby.client.am.PreparedStatement.flowExecute(Unknown Source)
at org.apache.derby.client.am.PreparedStatement.executeUpdateX(Unknown Source)
... 71 more
谢谢你们
最佳答案
您的映射不正确;您应该在使用@JoinColumn时在OneToOne和ManyToOne映射上使用@PrimaryKeyJoinColumn,而在OneToMany映射上应将@JoinColumn指定由其他关系映射时,请使用@JoinColumn。
在SalesInvoice中尝试:
@ManyToOne
@JoinColumn(name="STORE_ID", referencedColumnName="STORE_ID")
private Store store;
@ManyToOne
@JoinColumn(name="CUST_ID", referencedColumnName="CUST_ID")
private Customer customer;
@OneToMany(mappedBy="invoice",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
private List<InvoiceLine> lines;
@ManyToOne
@JoinColumn(name="TECH_ID",referencedColumnName="TECH_ID")
private Technician technician;
在InvoiceLine中时,请尝试:
@ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@JoinColumn(name="INV_ID", referencedColumnName="INV_ID")
private SalesInvoice invoice;
这是使SalesInvoice-InvoiceLine双向关系的方式。不要忘记,应用程序负责使双向关系的双方与数据库和彼此保持同步。 JPA不会为您执行此操作,并且缓存将损坏。
您还需要删除长invoiceID映射,使其成为只读或设置值,因为这是在先前实体设置中用于设置“ INV_ID”字段的内容-这很可能是您使用@PrimaryKeyJoinColumn作为提供者会抱怨您否则有多个可写映射。评估其目的,并在不需要时将其删除,否则我将使用以下方式将其设为只读:
@Column(name="INV_ID", insertable=false, updatable=false)
private long invoiceID;
因为这将允许您将属性保留在实体中,但让JPA改为使用发票关系中的值进行设置。