我有以下實體:OpenJPA的級聯堅持一個一對多與@EmbeddedId
發票
@Entity
@Table(name = "invoice")
public class Invoice implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "InvoiceID")
private Long invoiceID;
@Basic(optional = false)
@Column(name = "Date")
@Temporal(TemporalType.DATE)
private Date date;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "invoice")
private List<Invoiceitem> invoiceitemCollection;
@JoinColumn(name = "CustomerID", referencedColumnName = "CustomerID")
@ManyToOne(fetch = FetchType.LAZY,optional = false)
private Customer customerID;
// getter/setter
}
Invoiceitem
@Entity
@Table(name = "invoiceitem")
public class Invoiceitem implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected InvoiceitemPK invoiceitemPK;
@Basic(optional = false)
@Column(name = "Quantity")
private int quantity;
@JoinColumn(name = "InvoiceID", referencedColumnName = "InvoiceID", insertable = false, updatable = false)
@ManyToOne(optional = false)
private Invoice invoice;
@JoinColumn(name = "ProductID", referencedColumnName = "ProductID")
@ManyToOne(optional = false)
private Product productID;
// getter/setter
}
InvoiceItemPK
@Embeddable
public class InvoiceitemPK implements Serializable {
@Column(name = "ItemID" ,nullable=false)
private long itemID;
@Column(name = "InvoiceID", nullable=false)
private long invoiceID;
// getter/setter
}
這是3層獨立的應用程序,我需要做以下幾點: 測試1.每個10-發票加10 invoiceitem .... ....
STEP 1,填寫發票 - Invoiceitem:
for(int i = 0; i < invoiceNumber; i++){
// set invoice where invoiceNumber = 10, 100
Invoice invoice = new Invoice();
String formatIn = "dd-MM-yyyy";
SimpleDateFormat sdfi = new SimpleDateFormat(formatIn);
java.util.Date inDate = sdfi.parse("29-04-2011");
java.sql.Date sqlDate = new java.sql.Date(inDate.getTime());
invoice.setCustomerID(newCust);
invoice.setDate(sqlDate);
// set Invoiceitem
setInvoiceItem(prod, invItemNumber, invoice);
saveInvoice(invoice);
}
方法setInvoiceItem,
List<Invoiceitem> invoiceItemList = new ArrayList<Invoiceitem>();
for(int i = 0; i < invItemNumber ; i++){
// set invoiceitem where invItemNumber = 10, 100
Invoiceitem invoiceItem = new Invoiceitem();
int quantity = new RandomGeneratorForInteger().generateRandomNumber(10);
int genProductID = new RandomGeneratorForInteger().generateRandomNumber(ProductCollectionOpenJPA.getProdIDLi().size());
Long pid = (Long) ProductCollectionOpenJPA.getProdIDLi().get(genProductID);
// set relation
invoiceItem.setInvoice(invoice);
invoiceItem.setProductID(prod = new Product(pid));
invoiceItem.setQuantity(quantity);
invoiceItemList.add(invoiceItem);
}
invoice.setInvoiceitemCollection(invoiceItemList);
我有通用的DAO
public void insert(E entity) {
try {
EntityManager em = getEntityManager();
em.persist(entity);
} catch (Exception e) {
rollbackTransaction();
e.printStackTrace();
}
}
STEP 2,InvoiceService - persit發票
public String save(Invoice invoice) {
InvoiceDAO.log("saving Invoice---> InvoiceItem instance", Level.INFO, null);
try {
inDAO.beginTransaction();
inDAO.insert(invoice);
for (int i = 0; i < invoice.getInvoiceitemCollection().size(); i++) {
InvoiceitemPK inItmPK = new InvoiceitemPK();
inItmPK.setItemID(++i);
inItmPK.setInvoiceID(invoice.getInvoiceID());
invoice.getInvoiceitemCollection().get(i).setInvoiceitemPK(inItmPK);
for (int i = 0; i < invoice.getInvoiceitemCollection().size(); i++) {
inDAO.insert(invoice);
}
inDAO.commitTransaction();
} catch (Exception e) {
InvoiceDAO.log("save failed", Level.SEVERE, e);
return "Invoice are't saved";
}
inDAO.closeEntityManager();
InvoiceDAO.log("save successful", Level.INFO, null);
return "Invoice successfuly saved";
}
運行的應用程序的錯誤獲得: 1. org.apache.openjpa .persistence.ArgumentException:嘗試將id「domainopenjpa.Invoiceitem-null」分配給新實例「[email protected] 11「失敗; 2. org.apache.openjpa.persistence.ArgumentException:不能設定值
...
什麼是堅持到發票數據庫的最佳方式? 我在哪裏犯了一個錯誤,以及如何糾正?
裏克嗨,
異常堆棧看起來是這樣的:
<openjpa-2.0.1-r422266:989424 fatal general error> org.apache.openjpa.persistence.PersistenceException: This operation failed for some instances. See the nested exceptions array for details.
at org.apache.openjpa.kernel.BrokerImpl.throwNestedExceptions(BrokerImpl.java:2493)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2179)
at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2037)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1808)
at org.apache.openjpa.kernel.StateManagerImpl.assignObjectId(StateManagerImpl.java:609)
at org.apache.openjpa.kernel.StateManagerImpl.assignField(StateManagerImpl.java:696)
at org.apache.openjpa.kernel.StateManagerImpl.beforeAccessField(StateManagerImpl.java:1608)
at org.apache.openjpa.kernel.StateManagerImpl.accessingField(StateManagerImpl.java:1591)
at domainopenjpa.Invoice.pcGetinvoiceID(Invoice.java)
...
Caused by: <openjpa-2.0.1-r422266:989424 fatal general error> org.apache.openjpa.persistence.PersistenceException: The transaction has been rolled back. See the nested exceptions for details on the errors that occurred.
at org.apache.openjpa.kernel.BrokerImpl.newFlushException(BrokerImpl.java:2302)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2139)
... 77 more
Caused by: <openjpa-2.0.1-r422266:989424 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: cant-set-value
at org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy.insert(HandlerFieldStrategy.java:132)
at org.apache.openjpa.jdbc.meta.FieldMapping.insert(FieldMapping.java:623)
at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.insert(AbstractUpdateManager.java:230)
at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.populateRowManager(AbstractUpdateManager.java:162)
at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:95)
at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:76)
at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:731)
at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
... 78 more
NestedThrowables:
<openjpa-2.0.1-r422266:989424 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: Attempt to assign id "domainopenjpa.Invoiceitem-null" to new instance "[email protected]" failed; there is already an object in the L1 cache with this id. You must delete this object (in a previous transaction or the current one) before reusing its id. This error can also occur when a horizontally or vertically mapped classes uses auto-increment application identity and does not use a hierarchy of application identity classes.
FailedObject: [email protected]
at org.apache.openjpa.kernel.ManagedCache.assignObjectId(ManagedCache.java:193)
at org.apache.openjpa.kernel.BrokerImpl.assignObjectId(BrokerImpl.java:4949)
at org.apache.openjpa.kernel.BrokerImpl.setStateManager(BrokerImpl.java:4046)
at org.apache.openjpa.kernel.StateManagerImpl.assertObjectIdAssigned(StateManagerImpl.java:636)
at org.apache.openjpa.kernel.StateManagerImpl.afterFlush(StateManagerImpl.java:1084)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2162)
at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2037)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1808)
at org.apache.openjpa.kernel.StateManagerImpl.assignObjectId(StateManagerImpl.java:609)
at org.apache.openjpa.kernel.StateManagerImpl.assignField(StateManagerImpl.java:696)
at org.apache.openjpa.kernel.StateManagerImpl.beforeAccessField(StateManagerImpl.java:1608)
at org.apache.openjpa.kernel.StateManagerImpl.accessingField(StateManagerImpl.java:1591)
at domainopenjpa.Invoice.pcGetinvoiceID(Invoice.java)
at domainopenjpa.Invoice.getInvoiceID(Invoice.java:64)
新的異常堆棧:
<openjpa-2.0.1-r422266:989424 fatal user error> org.apache.openjpa.persistence.InvalidStateException: Encountered unmanaged object in persistent field "domainopenjpa.Invoice.invoiceitemCollection<element:class domainopenjpa.Invoiceitem>" during flush. However, this field does not allow cascade persist. Set the cascade attribute for this field to CascadeType.PERSIST or CascadeType.ALL (JPA annotations) or "persist" or "all" (JPA orm.xml), or enable cascade-persist globally, or manually persist the related field value prior to flushing. You cannot flush unmanaged objects or graphs that have persistent associations to unmanaged objects.
FailedObject: [email protected]
好吧,但是當我嘗試設置InvoiceitemPK時,我爲InvoiceID,InvoiceID自動增量和因爲我試圖做的這種方式得到null。 – Milan 2011-06-06 23:38:42
陷阱。您可以刪除Cascade.ALL,並在您的Invoice上調用persist(並可能是flush)之後,將ID取出放入InvoiceItem。 – Rick 2011-06-07 01:39:30
當我做下面的事情時,我得到了豁免女巫顯示在上面,**新的異常堆棧:**。第一步將_ @ OneToMany(cascade = CascadeType.ALL,mappedBy =「invoice」)更改爲@OneToMany(mappedBy =「invoice」)_,第二步在方法** Save(發票inv){** persist Invoice和getID,之後在for循環中創建InvoiceitemPK併爲每個InvoiceItem設置InvoiceID和ItemID。 – Milan 2011-06-08 21:21:09