请伙计们咨询
在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改为使用发票关系中的值进行设置。

10-05 19:48