为以下两个问题提供解决:
1. Hibernate cascade="all-delete-orphan"应用;
2. 用Collection or List 等集合时,迭代remove操作引起的java.util.ConcurrentModificationException问题
/** 修改業務系統 */
public String updateBuinessSys() {
modify = true;
String transId = (String) getRequestMap().get("transId");
if (StringUtil.isNullOrBlank(transId)) {
context.addMessage(null, new FacesMessage("不能獲取業務系統對象"));
return null;
}
Transaction transaction = transactionsManager.getTransactionById(transId);
if (transaction != null) {
transaction.setTransName(transName);
transaction.setTransCode(transCode);
transaction.setTransDesc(transDesc);
transaction.setEnterpriseCodes(enterpriseCodes);
transaction.setBankCodes(bankCodes);
String transFuncXml = context.getExternalContext().getRequestParameterMap().get("transFuncXml");
assembleTransFuncs(transFuncXml);
Set<String> newFunIdSet = new HashSet<String>();//新增的列表id set
Set<String> dbFunIdSet = new HashSet<String>();//DB中的列表id set
List<TransFunction> funList = transaction.getTransFunctions();
for (Iterator iterator = funList.iterator(); iterator.hasNext();) {
TransFunction fun = (TransFunction) iterator.next();
dbFunIdSet.add(fun.getId());
}
for (Iterator iterator = transFunList.iterator(); iterator.hasNext();) {
TransFunction fun = (TransFunction) iterator.next();
if (StringUtil.isNotNullOrBlank(fun.getId())) {
newFunIdSet.add(fun.getId());
}
}
/* 先remove,後add則不需要判斷fun.id為null的情況 */
for (Iterator iterator = funList.iterator(); iterator.hasNext();) {
TransFunction fun = (TransFunction) iterator.next();
if (!newFunIdSet.contains(fun.getId()))//如果保存的list中的ID在DB中不存在了,即已經被刪除了,則remove from list,使之成為orphan
//funList.remove(fun); 這一句會引起java.util.ConcurrentModificationException
iterator.remove();
}
for (Iterator iterator = transFunList.iterator(); iterator.hasNext();) {
TransFunction fun = (TransFunction) iterator.next();
if (StringUtil.isNullOrBlank(fun.getId()) || !dbFunIdSet.contains(fun.getId()))
funList.add(fun);//新增的記錄在DB中沒有,則認為是新增的記錄,加入到list當中去
}
//transaction.setTransFunctions(transFunList); 不需要重新設置,設定了all-delete-orphan即可
transactionsManager.saveOrUpdate(transaction);
return "viewBusinessState";
}
context.addMessage(null, new FacesMessage("無效的表單參數"));
return Constants.ERROR;
}
Transaction - TransFunction是一对多的关系: hbm.xml配置档如下:
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.domain">
<class name="Transaction" table="SYS_TRANS">
<id name="id" column="ID" length="32" type="string">
<generator class="uuid" />
</id>
<property name="transName" column="NAME" length="30" />
<property name="transCode" column="CODE" length="10" unique="true" />
<property name="transDesc" column="DESCR" length="200" />
<property name="enterpriseCodes" column="ENTP_CODES" length="1000" />
<property name="bankCodes" column="BANK_CODES" length="1000" />
<bag name="transFunctions" cascade="all-delete-orphan" inverse="false" lazy="false">
<key column="TRANS_ID" />
<one-to-many class="TransFunction" />
</bag>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.domain">
<class name="TransFunction" table="SYS_TRANS_FUNC">
<id name="id" column="ID" length="32" type="string">
<generator class="uuid" />
</id>
<property name="funcName" column="NAME" length="30" />
<property name="funcCode" column="CODE" length="20" unique="true" />
<many-to-one name="transaction" column="TRANS_ID"/>
</class>
</hibernate-mapping>