AndroMDA Getting started(七)
14.TimeTrackingService定义
我们现在处于迭代2阶段。这个迭代的目标是要构建搜索结果界面。要刷新我们的内存,下面是搜索屏幕的模型。搜索结果界面是时间卡显示的右面的内容。
Value Objects
要支持搜索结果面板,服务层必须提供根据匹配的特定规则获取timecard列表的能力。让我们决定我们创建一个service叫做TimeTrackingService,提供需要的功能:
public interface TimeTrackingService
{
public TimecardSummaryVO[] findTimecards(TimecardSearchCriteriaVO criteria);
}
有一个TimecardSearchCriteriaVO是value object,timecard包搜索条件-如果在这个类中的一个字段被指定,这个搜索条件就被应用了;如果这个filed被保留为null,则那个查询条件不会被用到。TimecardSummaryVO是另外的一个VO,在summary information包中。基于在Search屏幕中的条件,让我们来设计这两个VO。注意,我们需要一个状态field,在所有的Value Object中包含。因此首先,创建一个项目叫做TimecardStatus在org.andromda.timetracker.domain包中。在”Domain Objects”图中创建一个类,把sterotype设置为Enumeration。像下面显示的那样,这些被增加到属性中。确认enumeration被创建在org.andromda.timetracker.domain包中。
TimecardStatus被定义了,我们能定义被findTimecards()服务方法使用的两个value object。创在org.andromda.timetracker.vo包中建立TimecardSearchCriteriaVO和TimecardSummaryVO。在”Value Objects”图中创建这些value object。在TimecardSearchCriteriaVO中的每个属性的多重性被设置为0..1-指出他们的值可以有或没有。要指定一个属性的多重性,你必须在属性上双击打开它的描述,然后选择正确的多重性。在另外的两个value objects,创建一个类叫做TimecardSummaryVO[]来表现timecard summary数组。确保这三个类被创建在org.andromda.timetracker.vo包中。
TimeTrackingService
我们现在已经有了定义我们的TimeTrackingService的任何东西。在org.andromda.timetracker.service包中创建这个服务。在”Services”图中创建并且确保服务被创建在org.andromda.timetracker.service包中。已经确保findTimecards方法的返回类型为TimecardSummaryVO[]。
现在,让我们要求AndroMDA来生成代码:
1.在命令提示符中,执行mvn install。确保你看到了BUILD SUCCESSFUL消息。验证下面的文件会被生成:
- common/target/src/org/andromda/timetracker/domain/TimecardStatus.java
- common/target/src/org/andromda/timetracker/vo/TimecardSummaryVO.java
- common/target/src/org/andromda/timetracker/vo/TimecardSearchCriteriaVO.java
- common/target/src/org/andromda/timetracker/service/TimeTrackingService.java
- core/target/src/org/andromda/timetracker/service/TimeTrackingServiceBase.java
- core/src/main/java/org/andromda/timetracker/service/TimeTrackingServiceImpl.java
TimeTrackingService Test
像UserService一样,我们首先要给TimeTrackingService写一个测试用例并且写实现来使测试通过。下面的步骤用来创建TimeTrackingServiceTest并且运行:
1.
从C:/timetracker-completed/core/src/test/java/org/andromda/timetracker/service
位置拷贝TimeTrackingServiceTest.java在你的实现的位置中。这个文件包括对findTimecards()方法的两个测试,testFindAllTimecards()和testFindTimecardsForSubmitter。确保你确认和理解这些测试。
2.
编辑在C:/timetracker/core/src/test/resources目录下的testng.xml,取消注释TimeTrackingServiceTest以便能执行。
3.
执行下面的命令,在C:/timetracker目录来运行测试。
Mvn –f core/pom.xml test
你可以看到下面的错误信息,说明了测试失败:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running Services Test
Tests run: 3, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.661 sec <<< FAILURE!
Results :
Tests run: 3, Failures: 2, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] There are test failures.
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19 seconds
[INFO] Finished at: Sun Aug 06 18:38:26 EDT 2006
[INFO] Final Memory: 5M/11M
4.让我们看测试结果,看看发生了什么。打开c:/timetracker/core/target/surefire-reports/Services Test.txt。你可以看到下面的日志:
-------------------------------------------------------------------------------
Test set: Services Test
-------------------------------------------------------------------------------
Tests run: 3, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.661 sec <<< FAILURE!
testFindAllTimecards Time elapsed: 0.31 sec <<< FAILURE!
java.lang.NullPointerException
at ...(TimeTrackingServiceTest.java:58)
at ...(TimeTrackingServiceTest.java:41)
testFindTimecardsForSubmitter Time elapsed: 0.01 sec <<< FAILURE!
java.lang.NullPointerException
at ...(TimeTrackingServiceTest.java:58)
at ...(TimeTrackingServiceTest.java:50)
很明显,服务当前返回了null而不是TimecardSummaryVO[]。这个问题会当我们实现服务后被纠正。
15.TimeTrackingServcie实现
在这一章,我们会实现TimeTrackingService并且确保能通过测试。
我们会首先需要增强我们的领域模型来支持新value object TimecardSearchCriteriaVO并且TimecardSummaryVO。注意TimecardSearchCriteriaVO是一个简单的数据传输对象,来指定搜索参数。没有领域实体被需要表达这个概念。然而TimecardSummaryVO代表了timecard实体并且必须被增加到领域模型中。这个图如下面的显示:
Timecard与User实体有两个关系:
1. submitter:提交timecard的人。
2. approver:审核timecard的人。
两个关联关系的箭头指出了从Timecard到Person的方向。例如,timecard保持了对submitter和approver的饮用。在关联末端的数字和型号指明了多重性。顶端的关联指出timecard能有一个submitter,但是submitter能提交多个timecard(用*显示)。相似的,地下的关系指出了有0或1个审批者,一个审批者可以审批多个timecard。我们允许0审批者,以便审批是与提交延迟的。
我们在Timecard实体中增加一个方法叫做findByCriteria()。TimeTrackingService会使用这个方法来查找timecard。注意在findByCriteria()方法的下划线-他表示在UML中的”classifier”范围。如果在方法上没有下划线,会实现”instance”范围。这是在AndroMDA中重要的概念,特别注意。
一个带classifier scope的方法是一种一般目的的工具方法,操作一个或更多的实体。这样的方法在DAO类中被生成。带instance scope的方法生成在实体自己上并且被生成在Entity和EntityImpl类中。
我们现在准备增加Timecard实体到TimeTracker模型中,请根据下面的连接来继续。
- ArgoUML (under construction)
- MagicDraw 9.x
- MagicDraw 11.5
- RSM 6
接下来从Timecard实体到TimecardSummaryVO增加依赖关系。正如你所知,这种依赖告诉AndroMDA在Timecard和TimecardSummaryVO对象间生成转换。转换方法被生成在TimecardDaoBase中。然而,注意TimecardSummaryVO包含被从另外一个实体中获取的属性,叫做User,因此我们会覆盖默认的转换方法在这些其他的属性中。
接下来从TimeTrackingService到Timecard实体增加一个依赖。正如你所知,这个依赖告诉AndroMDA让TimeTrackingService访问Timecard实体。
现在,让我们要求AndroMDA为Timecard实体生成代码:
1.在命令提示符中执行mvn install。注意构建不会成功,因为测试仍然失败,然而代码生成的部分会成功。
Eclipse User:打开AndroMDA生成的.classpath文件。注意AndroMDA不会增加TestNG到classpath路径中。增加下面的条目到到这个文件中,以确保TestNG在Classpath中。如果你不想AndroMDA覆盖已经修改了的.classpath文件,通过注释在mda/pom.xml文件中的andromdapp-maven-plugin
段就可以了。
<classpathentry kind="var" path="M2_REPO/org/testng/testng/4.7/testng-4.7-jdk15.jar"/>
现在,让我们开始实现findByCriteria()方法,增加下面显示的粗体行在生成的TimeTrackingServiceImpl类中。
// license-header java merge-point
/**
* This is only generated once! It will never be overwritten.
* You can (and have to!) safely modify it by hand.
*/
package org.andromda.timetracker.service;
import java.util.List;
import org.andromda.timetracker.vo.TimecardSummaryVO;
/**
* @see org.andromda.timetracker.service.TimeTrackingService
*/
public class TimeTrackingServiceImpl
extends org.andromda.timetracker.service.TimeTrackingServiceBase
{
/**
* @see org.andromda.timetracker.service.TimeTrackingService#findTimecards(...)
*/
protected org.andromda.timetracker.vo.TimecardSummaryVO[] handleFindTimecards(
org.andromda.timetracker.vo.TimecardSearchCriteriaVO criteria)
throws java.lang.Exception
{
List timecards = getTimecardDao().findByCriteria(criteria);
getTimecardDao().toTimecardSummaryVOCollection(timecards);
return (TimecardSummaryVO[])timecards.toArray(new TimecardSummaryVO[0]);
}
}
我们首先在TimeDao中做一个调用findByCriteria()方法。还记得这是一个我们增加到Timecard实体的经典的方法吗?我们会手动实现这个方法。findByCriteria()
方法返回一个匹配Timecard实体的列表。然而,handleFindTimecards()需要返回一个TimecardSummaryVO对象的数组,因此,我们首先使用TimecardDao帮助方法来转换实体列表为VO集合。然后我们转换集合到一个数组,返回它。
现在在TimecardDaoImpl中实现handleFindByCriteria()方法。注意,代码使用Hibernate criteria查询来实现搜索功能。因此,我们无需关注实现细节,这在本教程的范围之外。
package org.andromda.timetracker.domain;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.criterion.Restrictions;
/**
* @see org.andromda.timetracker.domain.Timecard
*/
public class TimecardDaoImpl
extends org.andromda.timetracker.domain.TimecardDaoBase
{
...
protected java.util.List handleFindByCriteria(
org.andromda.timetracker.vo.TimecardSearchCriteriaVO criteria)
{
// Create the timecard criteria
Criteria timecardCriteria = this.getSession()
.createCriteria(Timecard.class)
.setFetchMode("submitter", FetchMode.JOIN)
.setFetchMode("approver", FetchMode.JOIN);
// Add submitter criteria
if (criteria.getSubmitterId() != null) {
timecardCriteria.createCriteria("submitter")
.add(Restrictions.idEq(criteria.getSubmitterId()));
}
// Add approver criteria
if (criteria.getApproverId() != null) {
timecardCriteria.createCriteria("approver")
.add(Restrictions.idEq(criteria.getApproverId()));
}
// Add status criteria
if (criteria.getStatus() != null) {
timecardCriteria.add(Restrictions.eq("status", criteria.getStatus()));
}
// Add startDateMin criteria
if (criteria.getStartDateMin() != null) {
timecardCriteria.add(
Restrictions.ge("startDate", criteria.getStartDateMin()));
}
// Add startDateMax criteria
if (criteria.getStartDateMax() != null) {
timecardCriteria.add(
Restrictions.le("startDate", criteria.getStartDateMax()));
}
java.util.List timecards = timecardCriteria.list();
if (logger.isDebugEnabled()) {
logger.debug(timecards.size() + " timecards found");
}
return timecards;
}
...
}
现在改变在TimecardDaoImpl类的TimecardSummaryVO()方法的默认实现,因为他不正确。注意,这个方法要被TimeTrackerService.findByCriteria()来调用,用来转换Timecard实体。目前,toTimecardSummaryVO()简单调用了在父类中的方法(TimecardDaoBase)。如果你还记得,在DaoBase中的默认的转换实现非常简单化。特殊的,TimecardDaoBase类只拷贝Timecard属性到TimecardSummaryVO;他不在从相关的实体的属性中填充,叫做submitterName和approverName。因此在TimecardDaoImpl类的TimecardSummaryVO()方法中做下面的修改:
public void toTimecardSummaryVO(
org.andromda.timetracker.domain.Timecard sourceEntity,
org.andromda.timetracker.vo.TimecardSummaryVO targetVO)
{
super.toTimecardSummaryVO(sourceEntity, targetVO);
targetVO.setSubmitterName(sourceEntity.getSubmitter().getUsername());
if (sourceEntity.getApprover() != null) {
targetVO.setApproverName(sourceEntity.getApprover().getUsername());
}
}
最后一件我们需要做的事情是在数据库中创建Timecard表并且填充数据。下面的步骤会完成这项工作:
1.
在命令提示符中运行下面的命令。要求androMDA创建我们的数据库schema:
Mvn –f core/pom.xml andromdapp:schema –Dtask=create
确保看到了构建成功的字样
2.
打开MySQL Query Browser。用timetracker登录。你能看到user和timecard表。
3.
选择文件->New Script粘贴下面的脚本
insert into USERS (ID, USERNAME, FIRST_NAME, LAST_NAME)
values (1, 'nbhatia', 'Naresh', 'Bhatia');
insert into USERS (ID, USERNAME, FIRST_NAME, LAST_NAME)
values (2, 'lcoude', 'Louis', 'Coude');
insert into USERS (ID, USERNAME, FIRST_NAME, LAST_NAME)
values (3, 'ecrutchfield', 'Eric', 'Crutchfield');
insert into USERS (ID, USERNAME, FIRST_NAME, LAST_NAME)
values (4, 'cmicali', 'Chris', 'Micali');
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values ( 1, 'Approved', '2006/05/15', 'Timecard 01', 1, 2);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values ( 2, 'Approved', '2006/05/15', 'Timecard 02', 2, 3);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values ( 3, 'Approved', '2006/05/15', 'Timecard 03', 3, 4);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values ( 4, 'Approved', '2006/05/15', 'Timecard 04', 4, 1);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values ( 5, 'Rejected', '2006/05/22', 'Timecard 05', 1, 2);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values ( 6, 'Rejected', '2006/05/22', 'Timecard 06', 2, 3);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values ( 7, 'Rejected', '2006/05/22', 'Timecard 07', 3, 4);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values ( 8, 'Rejected', '2006/05/22', 'Timecard 08', 4, 1);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values ( 9, 'Submitted', '2006/05/29', 'Timecard 09', 1, 2);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values (10, 'Submitted', '2006/05/29', 'Timecard 10', 2, 3);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values (11, 'Submitted', '2006/05/29', 'Timecard 11', 3, 4);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values (12, 'Submitted', '2006/05/29', 'Timecard 12', 4, 1);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values (13, 'Draft', '2006/06/05', 'Timecard 13', null, 2);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values (14, 'Draft', '2006/06/05', 'Timecard 14', null, 3);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values (15, 'Draft', '2006/06/05', 'Timecard 15', null, 4);
insert into TIMECARD (ID, STATUS, START_DATE, COMMENTS, APPROVER_FK, SUBMITTER_FK)
values (16, 'Draft', '2006/06/05', 'Timecard 16', null, 1);
2.
在顶端靠右点击执行按钮。
好,我们认为TimeTrackingService现在完成了。让我们执行下面的命令来再次运行测试,并且看看发生了什么:
C:/timetracker>mvn -f core/pom.xml test
...
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running Services Test
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.272 sec
Results :
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 30 seconds
[INFO] Finished at: Fri Aug 11 21:05:53 EDT 2006
[INFO] Final Memory: 6M/14M
[INFO] ------------------------------------------------------------------------
棒极了!所有的测试都通过了。打开文件C:/timetracker/core/timetracker-test.log,
21:05:46.850 INFO - Initializing ServiceLocator
21:05:46.870 INFO - Initializing UserService
21:05:51.767 INFO - Initializing ServiceLocator
21:05:51.767 INFO - Initializing TimeTrackingService
21:05:51.858 INFO - testFindAllTimecards:
...
21:05:52.819 DEBUG - 16 timecards found
21:05:52.859 INFO - Submitter Approver Status Start Date
21:05:52.869 INFO - nbhatia cmicali Approved 05/15/06
21:05:52.869 INFO - nbhatia cmicali Rejected 05/22/06
21:05:52.869 INFO - nbhatia cmicali Submitted 05/29/06
21:05:52.869 INFO - nbhatia null Draft 06/05/06
21:05:52.869 INFO - lcoude nbhatia Approved 05/15/06
21:05:52.869 INFO - lcoude nbhatia Rejected 05/22/06
21:05:52.869 INFO - lcoude nbhatia Submitted 05/29/06
21:05:52.869 INFO - lcoude null Draft 06/05/06
21:05:52.869 INFO - ecrutchfield lcoude Approved 05/15/06
21:05:52.869 INFO - ecrutchfield lcoude Rejected 05/22/06
21:05:52.869 INFO - ecrutchfield lcoude Submitted 05/29/06
21:05:52.869 INFO - ecrutchfield null Draft 06/05/06
21:05:52.869 INFO - cmicali ecrutchfield Approved 05/15/06
21:05:52.869 INFO - cmicali ecrutchfield Rejected 05/22/06
21:05:52.869 INFO - cmicali ecrutchfield Submitted 05/29/06
21:05:52.869 INFO - cmicali null Draft 06/05/06
21:05:52.879 INFO - testFindTimecardsForSubmitter:
...
21:05:52.959 DEBUG - 4 timecards found
21:05:52.959 INFO - Submitter Approver Status Start Date
21:05:52.969 INFO - nbhatia cmicali Approved 05/15/06
21:05:52.969 INFO - nbhatia cmicali Rejected 05/22/06
21:05:52.969 INFO - nbhatia cmicali Submitted 05/29/06
21:05:52.969 INFO - nbhatia null Draft 06/05/06
...
AndroMDA Getting started(七)相关推荐
- 今天的学生要做汤饭吗
Nineteen or so years ago, I imagine, today's college students were banging their spoons against thei ...
- 【C#实践】详解三层转七层:登录
背景 一开始借用别人的代码,敲完也是很多地方看不懂!不知道从什么地方下手!不懂三层到七层到底是怎么映射过去的! 后来就是多查,慢慢有大体的轮廓,逐个部分解决! 过程: 1.看整体,对于不懂的部分,先查 ...
- NLP进阶之(七)膨胀卷积神经网络
NLP进阶之(七)膨胀卷积神经网络 1. Dilated Convolutions 膨胀卷积神经网络 1.2 动态理解 1.2.2 转置卷积动画 1.2.3 理解 2. Dilated Convolu ...
- TVM性能评估分析(七)
TVM性能评估分析(七) Figure 1. Performance Improvement Figure 2. Depthwise convolution Figure 3. Data Fusion ...
- 2021年大数据Kafka(七):Kafka的分片和副本机制
全网最详细的大数据Kafka文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 Kafka的分片和副本机制 一.分片机制 二.副本机制 三. ...
- 2021年大数据HBase(七):Hbase的架构!【建议收藏】
全网最详细的大数据HBase文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 前言 Hbase的架构 一.Client 二.Master ...
- 2021年大数据Hive(七):Hive的开窗函数
全网最详细的Hive文章系列,强烈建议收藏加关注! 后面更新文章都会列出历史文章目录,帮助大家回顾知识重点. 目录 系列历史文章 前言 Hive的开窗函数 一.窗口函数 ROW_NUMBER,RANK ...
- 九零后的五年七次工作经历
1990年农历10月22生日(阴历),2008年上大学,2010年工作,至此,一路走过来.磕磕绊绊,酸甜苦辣.准备把自己的经历写出来,不敢谈什么启发,仅仅希望对他人稍有借鉴. 上过班.创过业.卖过小吃 ...
- ABAP性能实例七例
一.SQL Interface 1.Select ... Where vs. Select + Check 用Select - Where语句效率比Select + Check语句要高,例如: SEL ...
最新文章
- netsh命令修改ip
- 笔试题目“翻转字符串”的实现
- ZOJ1563 (动态规划)
- mysql哪些优化手段_mysql explain 及常见优化手段
- mariadb 10.2.3支持延时复制
- 第一次失效_神兵小将:净化之力失效地魔兵兽,全靠特殊办法,铁心方式真霸气...
- 在SqlServer 2008中将数据导成脚本
- 解决chrome/Edge提示您的连接不是私密连接的方法
- SQL反模式学习笔记15 分组
- python json解释器_Python JSON
- 转:java 进阶之路
- 目前游戏行业内部主要几款游戏引擎的技术对比
- nps内网穿透p2p隧道实战
- android 高通手机精品游戏合集
- Tableau数据分析-Chapter04标靶图、甘特图、瀑布图
- Log-normal distribution对数正态分布
- Multimodal Fusion(多模态融合)
- qt.network.monitor: Could not get the INetworkConnection instance for the adapter GUID.QT关闭时程序异常结束
- 安卓一键清理内存_微清理下载软件-微清理app下载v1.0.1.2 安卓版
- LoRA转4G及网关中继器工作原理
热门文章
- 【自动驾驶】高级辅助驾驶系统与车联网
- codeforces 849B Tell Your World(计算几何)
- 基于JavaScript实现的网页版贪吃蛇
- Java微信公众号开发(附源码!!!)
- 飞机机器人特摄片_机器人大战怪兽-好莱坞的特摄片「环太平洋」
- 子网掩码是什么,IP段的24是什么写法(CIDR写法,斜杠记法斜线记法)
- 码斗士的修炼之路 -- 如何保持并提升战斗力
- 在kile中为stm32移植FreeRTOS
- amd显卡多屏识别了 但是屏幕不亮_最近发布:针对AMD显卡多屏显示设置的完整解决方案。ppt28...
- TCP连接耗尽攻击异常报文攻击与防御