回到目录
Lesson 4:获取并使用Manager和DAO
每个XML中定义的模型都会生成对应的Manager和DAO,用于提供基础的功能。(参见 <DaaS 概要与建模> 中 ‘JAVA源代码目录介绍’ 一节)
在 Manager Bean 中获取 Manager 和 DAO
在每个ManagerBean中提供了快捷方式获取模型对应的Manager。
例如bank.xml中有定义“change_request”, 那么得到它的Manager如下:
changeRequestManagerOf(ctx)....
下图为使用ChangeRequestManager创建一条新记录的示例。
获取DAO的方式类似,代码为:
changeRequestDaoOf(ctx)
下为增加了DAO后的代码示例:
public Object getThenUserManagerAndDao(BankUserContext ctx) throws Exception {
ChangeRequest r1 = changeRequestManagerOf(ctx)
.createChangeRequest(ctx, "name", ChangeRequestType.DEPOSITE, "P000001");
ChangeRequest r2 = changeRequestDaoOf(ctx)
.load(r1.getId(), ChangeRequestTokens.withoutLists());
return CollectionUtils.toList(r1,r2);
}
使用‘gradle bootRun’, 编译运行; 再使用postMan访问以上接口,截图如下:
在 Manager Bean 以外的地方获取Manager和DAO
Manager Bean里的xxxManagerOf(ctx)是一个快捷的包装。
在某些情况下,例如工具方法类中,需要获取某个Manager和DAO,可以直接使用UserContext:
userContext.getManagerGroup().getChangeRequestManager()... userContext.getDAOGroup().getChangeRequestDAO()...
使用Manager
xxxManager的方法,在得到它后就可以调用了。
您可以查看源代码获得所有的细节。这里简要介绍一下几类API。
上面的例子中,可以看到返回的结果,是两个JSON对象的数组,其中每个对象里展开了一些对象:
这个展示了 Manager 中的createXXX() 方法和DAO中的load()方法。
Create方法
createXXX() 方法的参数,第一个仍然是UserContext,然后是按照XML中定义的顺序出现的必须的参数。 例如上例中定义的模型为:
那么"name", "request_type","plateform"是需要输入的 (参见<DaaS 概要与建模>),其他属性:create_time, remote_ip 则不会。所以看到的调用方法为:
changeRequestManagerOf(ctx).createChangeRequest(ctx,"name",ChangeRequestType.DEPOSITE,"P000001");
Save 方法
Save类的方法包括updatexxx..; ...save....等,请查看您手上的每次生成的源代码 “public interface XXXManager” 中的定义,如本例中的:updatexxx() 方法是更新属性值的,用于‘编辑即保存’的场景; internalSave系列方法则是保存整个对象的,用于‘提交再保存’的场景;
Load 方法
loadXXXX方法的定义及实现,请查看您手中生成的源代码。load方法很简单
Token
在save/load方法中,可以看到一个参数 tokens,或者叫‘options’:
Token 是用来控制‘范围’的。
每个模型都会有对应的Tokens类生成,方便使用。例如:
// 只涉及ChangeRequest对象本身
Map<String, Object> tok1 = ChangeRequestTokens.empty();
// 涉及ChangeRequest对象本身,以及被他直接引用的对象;
Map<String, Object> tok2 = ChangeRequestTokens.withoutLists();
// 涉及ChangeRequest对象本身,以及被他直接引用的RequestType对象
Map<String, Object> tok3 = ChangeRequestTokens.start().withRequestType().done();
例如load中使用tok3,则它不会加载platform,而只会加载requestType。
transfer方法
transfer方法用于在不同的‘引用’对象中切换。
例如本例中的 requestType,当我们想从一个type,切换到另外一个type时,就可以调用:
ChangeRequest r1 = ...
changeRequestManagerOf(ctx).transferToAnotherRequestType(
ctx,
r1.getId(), // 要做transfer的对象ID
ChangeRequestType.WITHDRAW); // 新的引用对象的ID
delete 方法
delete方法需要说明的是,默认不做真实的数据库删除,只是将被删除对象中,直接引用的其他对象断开(置为null)。
成员操作方法
默认的,为模型的‘子对象列表’提供了快捷操作。包括 add、remove,udpdate
使用DAO
默认会生成"XXXJDBCTemplateDAO.java",它实现了接口“XXXDAO”(是的,你可以在你手中已经生成的代码中看到)。
CRUD 方法
CRUD类的方法,通过简单的名字即可看出接口的功能。例如
这些就不详细讲了,源代码也很简洁。
find 方法
find类的方法是对‘查询’功能的一种封装,提供简洁的调用,例如:
-
注意这里又出现了 ‘options’。 此处的options是指‘find’的范围。因此它返回的结果不会作用于加载的对象本身,而只是和查询相关的部分。 例如:
changeRequestDaoOf(ctx).findChangeRequestByRequestType( ChangeRequestType.CHANGE_NAME, PlatformTokens.start() .searchChangeRequestListWith(ChangeRequest.CREATE_TIME_PROPERTY, "between","2012-12-21~2019-12-21") .sortChangeRequestListWith(ChangeRequest.REQUEST_TYPE_PROPERTY, "asc") .done() );
它生成的查询语句在日志中可以看到:
SQL为:
select * from change_request_data
where request_type = 'CHANGE_NAME'
and create_time between '2012-12-21' and '2019-12-21'
order by request_type asc;
这里的 3,4 行就是tokens的作用。
token 在find类接口中的使用,还在不断的更新中。DAO中还提供了基础的JDBC接口 queryList:
public SmartList<ChangeRequest> queryList(String sql, Object ... parmeters);
这个接口就非常简单了,自己写SQL,构造parameters即可。
enhance类方法
以本例中的‘ChangeRequest’为例:会有以下几种enhance类的接口:
-
public void collectAndEnhance(BaseEntity ownerEntity);
这个接口用于,在用户持有本对象的上级对象时,加载上级对象中引用的本对象。
-
public SmartList loadOurTransactionList(BankUserContext userContext, List us, Map<String,Object> options) throws Exception;
-
public SmartList loadOurNameChangeEventList(BankUserContext userContext, List us, Map<String,Object> options) throws Exception;
-
public SmartList loadOurAccountChangeList(BankUserContext userContext, List us, Map<String,Object> options) throws Exception;
这几个接口用于从一个list中加载所有下级对象。
-
public ChangeRequest present(ChangeRequest changeRequest,Map<String, Object> options)
这个接口用于按照tokens增强子对象。默认的行为是:出现在token中的子对象(仅限于直接相关的一层范围)被加载出来,没有出现在token中的则不加载。
其他方法
其他还有count类接口,clone,requestCandidate等。这些代码的实现都很简单,在源代码中可以查看细节,功能也和名称一致,以后再详述。