事务一致性接口
本章节仅介绍报表数据查询与业务集成扩展后,如何保持事务一致性,填报事务一致性请参考《UniEAP Report填报模块使用手册》
在一些项目中,业务上需要保证和报表数据查询在同一个事务中,比如使用oracle实现数据的行级权限。实现事务一致性步骤如下:
1.数据源事务一致性配置
在Web应用的如下文件WEB-INF\conf\unieap\report\datasource.xml中,首先找到Category Name="rdb-sql"的节点,配置QuerierClass为JDBC实现类,如下代码所示;然后分别在Name属性值为northwind、sample1的DataSource子节点下新增属性TransactionName,值为在traxnsaction.xml中配置的transaction name,在本示例配置文件中,为default。而sample2数据源不需要保证事务一致性,则不配置TransactionName,当不配置时,该数据源的所有数据集更新,不在事务管理范围内。
需要特别说明的是,配置为相同TransactionName的所有数据源在同一个事务中,而不同的TransactionName并不在同一个事务中。没有配置TransactionName的数据源,不在统一事务管理的范围内。
<?xml version="1.0" encoding="UTF-8"?>
<DataSourceManager xmlns="http://www.neusoft.com/report/datasource"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.neusoft.com/report/datasource">
<Category Name="rdb-sql" Caption="关系数据库SQL数据源"
SourceClass="com.neusoft.unieap.dataset.datasource.impl.JDBCDataSource"
QuerierClass="com.neusoft.unieap.dataset.executer.jdbc.JDBCDataSetExecuter">
<DataSource Name="northwind" TransactionName="default" Caption="Report样例库"></DataSource>
<DataSource Name="sample1" TransactionName="default" Caption="sample1样例"></DataSource>
<DataSource Name="sample2" Caption="sample2样例"></DataSource>
</Category>
……
简单SQL数据集同复杂SQL数据集的事务配置方法基本相同,参照rdb-sql 修改rdb-sql-simple 节点内的DataSource即可。
2.代码实现
通过继承报表的Action方式的一个示例讲解如何实现查询事务一致性,EntryReportAction为报表生成的一个Action,将该类继承后,修改struts-config.xml文件为对应的新类即可,代码如下:
public class TransactionResultAction extends EntryReportAction {
protected ActionForward generateReport(ActionMapping map,
HttpServletRequest request) throws UnsupportedEncodingException {
ActionForward forward = null;
String reportId = request.getParameter("reportId");
DefineReport rDefine = DefineReportUtil.getDefineReport(reportId);
List dataSets = rDefine.getDataSetEntities();
DataSetDef dataSetDef = null;
String dsType = null, dsName = null;
if (dataSets != null && dataSets.size() > 0) {
dataSetDef = (DataSetDef) dataSets.get(0);
} else {
// 没有任何数据集
}
dsName = dataSetDef.getProperty(DataSetDef.DS_NAME).getValue();
dsType = dataSetDef.getProperty(DataSetDef.DS_TYPE).getValue();
// for (int i = 0; i < dataSets.size(); i++) {
// }
// 以上逻辑用于获取报表定义中数据集的类型和名字,如果约定已经知道数据集的类型和名字,则不需要获取
ITransactionManager manager = null;
String transactionName = DataSourceManager.getInstance().getDataSource(
dsType, dsName).getTransactionName();
try {
if (transactionName != null) {
manager = TransactionManagerAdaptor
.getTransactionManager(transactionName);
manager.begin();
}
Connection conn = manager.getConnectionForDataSource(dsName);
String sql = "UPDATE ms_product SET product_name=? WHERE PRODUCT_ID='11' ";
PreparedStatement pstmt = null;
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "统一事务查询测试2");
pstmt.executeUpdate();
forward = super.generateReport(map, request);
// 统一事务结束
if (transactionName != null) {
manager = TransactionManagerAdaptor
.getTransactionManager(transactionName);
manager.commit();
}
} catch (Exception e) {
List errorList = ExceptionHandler.errorHandle(e);
System.err.println(((String[]) (errorList.get(0)))[0]);
request.setAttribute("error", errorList);
if (forward == null) {
forward = map.findForward("error");
}
// 统一事务回滚
if (transactionName != null) {
manager = TransactionManagerAdaptor
.getTransactionManager(transactionName);
manager.rollback();
}
} finally {
}
return forward;
}
}
……