Hi, I encounter a problem with CascadeType for a OneToMany
relationship, hopefully somebody can help ... Thanks.
I am using OpenJPA 1.0.3 that come with Apache Geronimo 2.1.3
Basically , I have a loop to create ProductionOrder and the
corresponding detail ProductionOrderMaterial
After debugging , it shows that in the 2nd loop , not only INSERT
statement is generated , there are several unnecessary UPDATE
statements triggered , cause PersistentException ..
Code
====
for loop
ProductionOrder productionOrder = new ProductionOrder();
productionOrder.setDocNo("0");
productionOrder.setQuantityOrder(node.getData().getTreeOriginalQuantityRequired()
* salesOrderMaterial.getQuantityOrder());
productionOrder.setMaterial(node.getData().getBomDetail().getMaterial());
for(TreeNode<BomTreeNodeData> child : productionOrderChildren)
{
ProductionOrderMaterial productionOrderMaterial = new
ProductionOrderMaterial();
productionOrderMaterial.setQuantityConsumed(0.0);
productionOrderMaterial.setCreateApp(rowInfo.getCreateApp());
productionOrderMaterial.setModifyApp(rowInfo.getModifyApp());
productionOrderMaterial.setCreateLogin(rowInfo.getCreateLogin());
productionOrderMaterial.setModifyLogin(rowInfo.getModifyLogin());
productionOrderMaterial.setSessionId(rowInfo.getSessionId());
// the below line will do a two-way link
between ProductionOrder and ProductionOrderMaterial
productionOrder.addProductionOrderMaterial(productionOrderMaterial);
}
// this line will do a _em.persist
productionOrderService.addProductionOrder(productionOrder);
end for loop
DEBUG Log
First loop
============
SELECT KEYFIELD FROM PrimaryKeys WHERE TABLENAME = ? FOR UPDATE
[params=(String) ProductionOrder]
UPDATE PrimaryKeys SET KEYFIELD = ? WHERE TABLENAME = ? AND KEYFIELD =
? [params=(long) 950, (String) ProductionOrder, (long) 900]
SELECT KEYFIELD FROM PrimaryKeys WHERE TABLENAME = ? FOR UPDATE
[params=(String) ProductionOrderMaterial]
UPDATE PrimaryKeys SET KEYFIELD = ? WHERE TABLENAME = ? AND KEYFIELD =
? [params=(long) 950, (String) ProductionOrderMaterial, (long) 900]
INSERT INTO ProductionOrder (id_ProductionOrder, prodo_Number,
prodo_QuantityOrder, prodo_QuantityReported, version, fk_Material,
createApp, createLogin, createTimestamp, modifyApp, modifyLogin,
modifyTimestamp, recordStatus, sessionId, fk_SalesOrder) VALUES (?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [params=(long) 900, (String) 0,
(double) 50.0, (double) 0.0, (int) 1, (long) 100, (String) TestClient,
(String) test, (Timestamp) 2009-02-13 13:54:12.319, (String)
TestClient, (String) test, (Timestamp) 2009-02-13 13:54:12.319,
(String) A, (String) , (null) null]
INSERT INTO ProductionOrderMaterial (id_ProductionOrderMaterial,
prodom_QuantityConsumed, prodom_QuantityRequired, version,
fk_ProductionOrder, fk_Material, fk_ProductionOrderOperation,
createApp, createLogin, createTimestamp, modifyApp, modifyLogin,
modifyTimestamp, recordStatus, sessionId) VALUES (?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?) [params=(long) 900, (double) 0.0, (double)
100.0, (int) 1, (long) 900, (long) 101, (null) null, (String)
TestClient, (String) test, (Timestamp) 2009-02-13 13:54:12.32,
(String) TestClient, (String) test, (Timestamp) 2009-02-13
13:54:12.32, (String) A, (String) ABC]
INSERT INTO ProductionOrderMaterial (id_ProductionOrderMaterial,
prodom_QuantityConsumed, prodom_QuantityRequired, version,
fk_ProductionOrder, fk_Material, fk_ProductionOrderOperation,
createApp, createLogin, createTimestamp, modifyApp, modifyLogin,
modifyTimestamp, recordStatus, sessionId) VALUES (?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?) [params=(long) 901, (double) 0.0, (double)
150.0, (int) 1, (long) 900, (long) 102, (null) null, (String)
TestClient, (String) test, (Timestamp) 2009-02-13 13:54:12.32,
(String) TestClient, (String) test, (Timestamp) 2009-02-13
13:54:12.32, (String) A, (String) ABC]
2nd Loop
==========
INSERT INTO ProductionOrder (id_ProductionOrder, prodo_Number,
prodo_QuantityOrder, prodo_QuantityReported, version, fk_Material,
createApp, createLogin, createTimestamp, modifyApp, modifyLogin,
modifyTimestamp, recordStatus, sessionId, fk_SalesOrder) VALUES (?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [params=(long) 901, (String) 0,
(double) 100.0, (double) 0.0, (int) 1, (long) 101, (String)
TestClient, (String) test, (Timestamp) 2009-02-13 13:54:12.363,
(String) TestClient, (String) test, (Timestamp) 2009-02-13
13:54:12.363, (String) A, (String) , (null) null]
INSERT INTO ProductionOrderMaterial (id_ProductionOrderMaterial,
prodom_QuantityConsumed, prodom_QuantityRequired, version,
fk_ProductionOrder, fk_Material, fk_ProductionOrderOperation,
createApp, createLogin, createTimestamp, modifyApp, modifyLogin,
modifyTimestamp, recordStatus, sessionId) VALUES (?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?) [params=(long) 902, (double) 0.0, (double)
1000.0, (int) 1, (long) 901, (long) 106, (null) null, (String)
TestClient, (String) test, (Timestamp) 2009-02-13 13:54:12.364,
(String) TestClient, (String) test, (Timestamp) 2009-02-13
13:54:12.364, (String) A, (String) ABC]
3 INSERT INTO ProductionOrderMaterial (id_ProductionOrderMaterial,
prodom_QuantityConsumed, prodom_QuantityRequired, version,
fk_ProductionOrder, fk_Material, fk_ProductionOrderOperation,
createApp, createLogin, createTimestamp, modifyApp, modifyLogin,
modifyTimestamp, recordStatus, sessionId) VALUES (?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?) [params=(long) 903, (double) 0.0, (double)
400.0, (int) 1, (long) 901, (long) 107, (null) null, (String)
TestClient, (String) test, (Timestamp) 2009-02-13 13:54:12.364,
(String) TestClient, (String) test, (Timestamp) 2009-02-13
13:54:12.364, (String) A, (String) ABC]
INSERT INTO ProductionOrderMaterial (id_ProductionOrderMaterial,
prodom_QuantityConsumed, prodom_QuantityRequired, version,
fk_ProductionOrder, fk_Material, fk_ProductionOrderOperation,
createApp, createLogin, createTimestamp, modifyApp, modifyLogin,
modifyTimestamp, recordStatus, sessionId) VALUES (?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?) [params=(long) 904, (double) 0.0, (double)
400.0, (int) 1, (long) 901, (long) 104, (null) null, (String)
TestClient, (String) test, (Timestamp) 2009-02-13 13:54:12.364,
(String) TestClient, (String) test, (Timestamp) 2009-02-13
13:54:12.364, (String) A, (String) ABC]
341703 QERP_EJB TRACE [ejbd 11] openjpa.jdbc.SQL - <t 19397104,
conn 32165850> [0 ms] spent
< below are unnecessary UPDATE statement >
UPDATE ProductionOrder SET version = ?, createApp = ?, createLogin =
?, createTimestamp = ?, modifyApp = ?, modifyLogin = ?,
modifyTimestamp = ?, recordStatus = ?, sessionId = ? WHERE
id_ProductionOrder = ? AND version = ? [params=(int) 2, (String)
TestClient, (String) test, (Timestamp) 2009-02-13 13:54:12.319,
(String) TestClient, (String) test, (Timestamp) 2009-02-13
13:54:12.365, (String) A, (String) , (long) 900, (int) 1]
UPDATE ProductionOrderMaterial SET version = ?, createApp = ?,
createLogin = ?, createTimestamp = ?, modifyApp = ?, modifyLogin = ?,
modifyTimestamp = ?, recordStatus = ?, sessionId = ? WHERE
id_ProductionOrderMaterial = ? AND version = ? [params=(int) 2,
(String) TestClient, (String) test, (Timestamp) 2009-02-13
13:54:12.32, (String) TestClient, (String) test, (Timestamp)
2009-02-13 13:54:12.365, (String) A, (String) ABC, (long) 901, (int)
2]
UPDATE ProductionOrderMaterial SET version = ?, createApp = ?,
createLogin = ?, createTimestamp = ?, modifyApp = ?, modifyLogin = ?,
modifyTimestamp = ?, recordStatus = ?, sessionId = ? WHERE
id_ProductionOrderMaterial = ? AND version = ? [params=(int) 2,
(String) TestClient, (String) test, (Timestamp) 2009-02-13
13:54:12.32, (String) TestClient, (String) test, (Timestamp)
2009-02-13 13:54:12.365, (String) A, (String) ABC, (long) 900, (int)
2]
Below are classes for reference
public class ProductionOrder extends BaseEntity
{
@OneToMany(cascade=
{CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.REMOVE}, fetch =
FetchType.EAGER, mappedBy="productionOrder",
targetEntity=ProductionOrderMaterial.class)
private List<ProductionOrderMaterial> productionOrderMaterials;
@PrePersist
void prePersist() throws BusinessException {
validate();
rowInfo.setRecordStatus("A");
java.util.Date today = new java.util.Date();
rowInfo.setModifyTimestamp(new java.sql.Timestamp(today.getTime()));
rowInfo.setCreateTimestamp(rowInfo.getModifyTimestamp());
System.out.println("[PrePersist] " + rowInfo.getCreateLogin());
}
@PreUpdate
void preUpdate() throws BusinessException {
if(rowInfo.getRecordStatus()!="D")
{
validate();
}
java.util.Date today = new java.util.Date();
rowInfo.setModifyTimestamp(new
java.sql.Timestamp(today.getTime()));
}
public class ProductionOrderMaterial extends BaseEntity
{
@ManyToOne
@JoinColumn(name="fk_ProductionOrder")
private ProductionOrder productionOrder;
@PrePersist
void prePersist() throws BusinessException {
validate();
rowInfo.setRecordStatus("A");
java.util.Date today = new java.util.Date();
rowInfo.setModifyTimestamp(new java.sql.Timestamp(today.getTime()));
rowInfo.setCreateTimestamp(rowInfo.getModifyTimestamp());
}
@PreUpdate
void preUpdate() throws BusinessException {
if(rowInfo.getRecordStatus()!="D")
{
validate();
}
java.util.Date today = new java.util.Date();
rowInfo.setModifyTimestamp(new
java.sql.Timestamp(today.getTime()));
}
}