2011年8月6日星期六

ADF_101:如何在一个事务中插入一对多关系的多个EO对象?

开发环境:JDeveloper 11.1.2.2.0 + Oracle XE Database 10gR2。

考虑这种情况:数据库中Departments表和Employees表是一对多的关系,在Employee表中有DepartmentId字段,并且作为外键约束。
也就是说,插入一个Employee对象时,必须要先知道DepartmentId。
如果Department对象不存在,那么就先要插入Department对象,得到DepartmentId后,再插入Employee对象。
使用ADF-BC如何调整这两次插入操作先后顺序呢?如何保证两次插入操作在一个事务之中呢?

首先假定Departments表和Employees表的主键都是通过Sequence获取的。
如何在程序中获取Sequence的下一个值,请参考《ADF-BC中EO常用操作代码之三:增加EO(1)

重要步骤说明:

1. 在AM中增加方法:

public void newEmployeeForNewDepartment(String firstName, String departmentName) {
Date date = new Date(Date.getCurrentDate());
Timestamp today = new Timestamp(date);

// 1. Create a new employee
EmployeesImpl newEmployee = createNewEmployee();
// 2. Create a new department
DepartmentsImpl newDepartment = createNewDepartment();
newDepartment.setDepartmentName(departmentName);
// 3. Set the department id to which the employee pertains
newEmployee.setDepartmentId(newDepartment.getDepartmentId());
newEmployee.setFirstName(firstName);
newEmployee.setLastName("Test");
newEmployee.setEmail(today.toString());
newEmployee.setHireDate(today);
newEmployee.setJobId("AD_VP");

// 4. Commit the transaction
getDBTransaction().commit();
// 5. Construct a bean to hold new supplier id and product id

System.out.println(newEmployee.getEmployeeId());
System.out.println(newDepartment.getDepartmentId());
}

private EmployeesImpl createNewEmployee() {
EntityDefImpl productDef = EmployeesImpl.getDefinitionObject();
return (EmployeesImpl)productDef.createInstance2(getDBTransaction(), null);
}

private DepartmentsImpl createNewDepartment() {
EntityDefImpl supplierDef = DepartmentsImpl.getDefinitionObject();
return (DepartmentsImpl)supplierDef.createInstance2(getDBTransaction(), null);
}


2. 定制Employees EO(即一对多关系中“多”的一方),重写方法:postChanges

public void postChanges(TransactionEvent e) {
// If current entity is new or modified
if (getPostState() == STATUS_NEW || getPostState() == STATUS_MODIFIED) {
// Get the associated department for the employee
DepartmentsImpl deptEO = (DepartmentsImpl)getDepartments1();
// If there is an associated department
if (deptEO != null) {
// And if it's post-status is NEW
if (deptEO.getPostState() == STATUS_NEW) {
// Post the department before posting this entity
deptEO.postChanges(e);
}
}
}
super.postChanges(e);
}

说明:重写后的逻辑保证当插入或修改Employees EO时,首先插入与其关联的Department EO。
也就是说,虽然在newEmployeeForNewDepartment方法中先插入的是Employee,但实际上经过重postChanges后,先插入的是Department(即一对多关系中“一”的一方)。
这样就可以保证在插入Employee时,可以得到其关联的DepartmentId。

3. 运行AM测试


Project 下载:ADF_BC_EO_MasterDetail.7z

参考文献:
1. 《Fusion Developer's Guide for ADF》 之 Controlling Entity Posting Order to Avoid Constraint Violations

没有评论: