首页 疯狂java实战演义_第10章_事务跟踪系统

疯狂java实战演义_第10章_事务跟踪系统

举报
开通vip

疯狂java实战演义_第10章_事务跟踪系统第12章 仿Foxmail的邮件客户端 第10章 事务跟踪系统 在企业应用中,我们经常会使用到一些事务跟踪系统,这些事务跟踪系统可以帮助我们有效的对事务进行跟踪、管理。例如有这样一个场景,当某公司的经理接收到一个事务(例如需要处理某张订单或者需要购买某些材料),而这个事务不必由自己亲自去解决的时候,可以使用事务跟踪系统创建一个事务,并将该事务分发到相应的员工去处理,员工接收到这个事务的时候,就可以对事务进行处理,并将每一阶段的处理结果保存到系统中,分发事务的管理者就可以时时刻刻了解事务的进展,对事务起到一定的监控作...

疯狂java实战演义_第10章_事务跟踪系统
第12章 仿Foxmail的邮件客户端 第10章 事务跟踪系统 在企业应用中,我们经常会使用到一些事务跟踪系统,这些事务跟踪系统可以帮助我们有效的对事务进行跟踪、管理。例如有这样一个场景,当某公司的经理接收到一个事务(例如需要处理某张订单或者需要购买某些材料),而这个事务不必由自己亲自去解决的时候,可以使用事务跟踪系统创建一个事务,并将该事务分发到相应的员工去处理,员工接收到这个事务的时候,就可以对事务进行处理,并将每一阶段的处理结果保存到系统中,分发事务的管理者就可以时时刻刻了解事务的进展,对事务起到一定的监控作用。在本章中,我们就使用Java开发一个简单的CS事务跟踪系统。 10.1 确定系统需求 开发事务跟踪系统前,我们需要确定该系统的需求,一旦确定了需求,我们在开发的过程中,就需要按照这些需求进行相关的设计,再按照这些需求去实现相应的功能。如果一开始没有确定好需求,那么在开发的过程中,就会产生一系列的问MATCH_ word word文档格式规范word作业纸小票打印word模板word简历模板免费word简历 _1714041372170_0,例如做到一定程度的时候,就会有点不知所措,因为业务还没有通。 整个事务跟踪系统的中心是事务,所有的操作都是围绕着事务进行的,管理人创建、分发事务,执行者处理事务,将事务的处理结果反馈给管理人,管理人可以查看事务的进行状况、事务的当前处理人等相关信息,如果事务处理完成,那么管理人就需要在系统外进行一些工作,例如某经理接到一个订单,需要他的手下去进行处理,就可以新建一个事务,分发到他的手下,接收到这个事务的员工,就要为完成这个事务进行工作,执行完该事务后,就将处理结果告诉系统,当经理看到事务的处理结果后,就可以在系统外告诉他的客户,我们已经发货了,请客户查收等。这里需要注意的是,我们并不是要做订单系统,只是做一个简单的事务跟踪系统。 当一个员工接收到一个事务的时候,如果他发现自己最近根本没有时间或者没有能力去处理,那么他可以将事务转发给另外的同事,让其帮忙处理,系统需要记录一条转发记录,让事务管理者可以了解这个情况,可以在这个过程中了解到手下的工作饱和度及处理事情的能力等信息。整个系统的大致需要就有这些,该系统的功能并不复杂,只要确定好需求,开发就更加简单。 10.2 建立界面 我们大概了解了系统的需求后,可以根据这些需求创建界面。本章与前面章节中的图书进存销管理系统一样,都是使用Swing创建系统界面,同样使用MySQL作为系统数据库。在本小节,我们先根据需求确定界面与系统交互。 10.2.1 登录界面 如果需要进行事务跟踪系统进行业务操作,需要通过登录进入。用户进行登录,可以让系统知道用户的身份,再根据这个身份去判断哪些功能可以使用或者不可以使用,也就是我们常说的权限问题。权限一般包括功能权限和数据权限,功能权限是指某个用户并不能看到这个功能,从而不能使用这个功能,数据权限是指用户的身份并不能去操作(查看)某些数据。本章的重点并不是权限,因此只需要做简单的权限即可。用户登录界面如图10.1所示。 图10.1 系统登录界面 登录界面十分简单,两个输入框和两个按钮即可,其中需要注意的是,密码框使用的是JPasswordField类,并不是JTextField。 10.2.2 我的事务界面 我的事务界面主要显示用户需要处理的事务,并提供一些操作这些事务的按钮,让用户可以对自己的事务进行处理,我的事务功能是每个用户都具有的功能,不需要加任务的权限判断,因此用户一登录事务跟踪系统,首先展现的就是该界面。我的事务界面如图10.2所示。 图10.2 我的事务界面 我的事务界面中,默认显示的是进行中的事务,该界面包括了如下操作: ​ 查询事务:根据事务的不同状态查询相应状态的事务,并显示到列表中。 ​ 完成事务:当用户执行完某个事务后,可以点击完成,告诉系统已经处理完该事务了。 ​ 转发事务:当用户没有时间或者没有能力执行该事务的时候,可以将该事务转发给其他处理人。 ​ 暂时不做:如果用户最近没有时间处理该事务(工作饱和),就可以将事务置为暂时不做状态,那么管理者就可以知道,该用户没有时间处理。 ​ 不做:如果用户觉得这个事务没有存在的意义或者根本就不打算完成这个事务,就可以将该事务的状态设置为“不做”的状态,让管理者知道,用户不会为该事务做任何的工作。 在本系统中,事务包括的状态在下面章节将会详细描述。我的事务界面主要是一个JTable对象,只需要为该JTable对象提供TableCellRenderer的类来渲染列表即可。 10.2.3 事务的完成、暂时不做、不做的处理界面 在我的事务界面,提供了完成、暂时不做与不做的事务处理功能,当用户点击了这些功能的时候,就需要提供一个界面,让用户进行相关的说明,例如用户点击了暂时不做,而该用户又想说明为什么暂时不做,因此系统需要提供一个处理界面。事务处理界面如图10.3所示。 图10.3 事务处理界面 事务处理界面提供一个JTextField来显示事务的标题,并提供一个JTextArea的文本框,让用户描述相关的信息。在这里需要注意的是,用户进行完成、暂时不做与不做的操作时,才会处理事务的界面,在我们的事务界面中,还有一个转发功能,在下面章节中描述。 10.2.4 事务转发界面 用户发现自己没有时间或者没有能力去完成该事务的时候,就可以使用事务的转发功能,将属于自己的事务转发给其他同事进行处理。事务转发界面与事务处理界面稍微有一点不同,该界面需要让用户去选择需要转发的人。事务转发界面如图10.4所示。 图10.4 事务转发界面 如图10.4所示,在事务转发界面中,有一个选择用户的按钮,当用户点击了选择用户时,就需要弹出用户列表的界面,让用户去选择需要转发的同事,用户选择界面在下面的用户管理章节中将会详细描述。 10.2.5 事务管理界面 事务管理界面主要让管理人员进行事务的管理,例如新增事务、查看事务 流程 快递问题件怎么处理流程河南自建厂房流程下载关于规范招聘需求审批流程制作流程表下载邮件下载流程设计 等,与我的事务界面一样,提供一个JTable对象,让管理人员可以清晰的了解各种状态的事务。这里需要注意的是,某一个事务管理者只能看到自己发起的事务,查看到事务的相关状态与流程后,就可以在系统外进行跟进与处理。事务管理界面如图10.5所示。 图10.5 事务管理界面 事务管理界面提供了如下功能: ​ 事务查询:可以查询各种状态的事务。 ​ 新建事务:创建一个新的事务,并为其指定处理人。 ​ 催办事务:如果一个事务的优先级较高,则可以催办该事务,让事务处理人知道,需要先对该事务进行处理。 ​ 置为无效:将一个事务设置为无效,那么事务执行人就可以知道不必为该事务进行任何的工作。 10.2.6 新建事务界面 事务管理者接收到一个新的事务,需要下发到自己的手下进行处理的时候,可以新建一个事务,并指定相关的处理人。新建的事务包括事务的标题、内容、完成时间、处理人等信息,当用户输入了事务的相关信息后,系统就将这些信息保存到数据库中。新建事务界面如图10.6所示。 图10.6 新建事务界面 如图10.6所示,新建事务中同样有一个选择用户的按钮,与事务转发界面一样,使用同一个界面作为用户选择界面。 10.2.7 用户选择界面 在事务转发界面与新建事务界面中,都有一个用户选择功能,当操作人需要进行用户选择的时候,就需要打开用户选择界面进行选择,在本章中,我们使用同一个界面来实现用户选择的功能。当操作人选择了某个用户后,只需要调用不同的方法即可。新建一个用户选择处理接口。 代码清单:code\transaction\src\org\crazyit\transaction\ui\handler\UserSelectHandler.java: public interface UserSelectHandler { /** * 在用户选择界面点击确定后执行的方法 * @param userId * @param realName */ void confirm(String userId, String realName); } 那么在用户选择界面中,只需要提供一个这样的接口即可,操作人选择了某一个用户后,只需要调用接口的confirm方法即可,不需要理会具体的实现。用户选择界面如图10.7所示。 图10.7 用户选择界面 那么操作人选择了用户后,就可以执行用户选择接口的confirm方法。 代码清单:code\transaction\src\org\crazyit\transaction\ui\dialog\SelectUserDialog.java: //用户选择处理类 private UserSelectHandler selectHandler; //构造器 public SelectUserDialog(UserSelectHandler selectHandler) { this.selectHandler = selectHandler; ... } //点击确定执行的方法 private void confirm() { //得到选择的用户id与真实名称 //调用用户选择处理类的方法 this.selectHandler.confirm(id, realName); this.setVisible(false); } 以上代码是用户选择界面的部分实现,注意以上代码的黑体部分,操作人点击了确定后,就执行confirm方法。这样,用户选择界面就可以实现重用的功能,因此在本章中,只有一个用户选择界面类。 10.2.8 用户管理界面 在实际应用中,还出现一系列的人员变动情况,例如有新的员工入职,有旧的员工离职,因此,我们需要为事务跟踪系统提供一个用户管理界面,让系统管理员可以轻易的管理各个用户。用户管理包括新增用户、删除用户等。用户管理界面如图10.2.8所示。 图10.2.8 用户管理界面 用户管理界面包括如下功能: ​ 查询用户:根据用户姓名查询相关的用户,在实现中我们使用模糊查询。 ​ 新建用户:新建一个用户并分配相应的角色。 ​ 删除用户:将该用户从系统中删除,这里需要注意的是,由于原来已经存在的用户可能正在执行某个事务,如果将其从数据库中删除,那么将会影响其他数据,因此我们可以将该用户进行逻辑删除,即不将该用户信息展示到用户管理界面中。 10.2.9 新建用户界面 新建一个用户,需要保存用户名(系统用户名)、用户密码、用户真实姓名与分配角色,新建了一个用户后,该用户就拥有了所分配的角色权限,就可以使用本系统中的相关功能。新建用户界面如图10.2.9所示。 图10.9 新建用户 在本章中,为了简单起见,我们内置三种用户角色:管理员、经理与员工,管理员可以使用系统的任何功能,经理不可以使用用户管理功能,员工只能使用我的事务功能。在本小节中,我们制定了系统的各个界面,并确定了系统的交互,界面中的各个组件均使用Swing的组件,在这里不再详细描述。在下面的章节中,我们将实现这些功能。 10.3 开发准备 在本章中,我们将系统分成三层结构,DAO层、业务逻辑层与视图层,DAO层用于进行数据库交互处理,业务逻辑层主要用于处理系统的相关业务,视图层主要是界面组件。如果有使用IoC容器,我们可以很轻松的对各层之间的组件进行管理,由于本章中并不涉及IoC容器,因此我们可以使用一个类来对这些组件(DAO、业务逻辑)进行管理。 10.3.1 数据转换工具类 在开发图书进存销管理系统的时候,我们使用Java的反射来对数据进行封装(详细请看图书进存销系统),在本章中,我们同样使用这一方式来对我们的数据进行转换,当执行查询的时候,我们将数据库中读取到的ResultSet对象转换成具体的某个Java对象。但有一个前提就是,Java对象中的属性名称必须要与数据库中的表字段名称一致。我们可以将图书进存销管理系统的工具拿来使用,以下是图书进存销系统的数据转换工具类的具体实现。 代码清单:code\transaction\src\org\crazyit\transaction\util\DataUtil.java: public class DataUtil { //将rs中的值封装成一个集合 public static Collection getDatas(Collection result, ResultSet rs, Class clazz) { try { while (rs.next()) { //创建类的实例 Object vo = clazz.newInstance(); //获取本对象的属性 Field[] fields = clazz.getDeclaredFields(); //获取父类的属性 Field[] superFields = clazz.getSuperclass().getDeclaredFields(); //父类的属性和自己的属性相加 Field[] allFields = addFields(superFields, fields); //遍历所有的属性 for (Field field : allFields) { //获得setter方法的方法名 String setterMethodName = getSetterMethodName(field.getName()); //获得setter方法 Method setterMethod = clazz.getMethod(setterMethodName, field.getType()); invokeMethod(rs, field, vo, setterMethod); } result.add(vo); } rs.close(); } catch (Exception e) { e.printStackTrace(); throw new DataException(e.getMessage()); } return result; } //执行一个方法, 从ResultSet中获取一个字段的数据, 调用vo的setter方法 private static void invokeMethod(ResultSet rs, Field field, Object vo, Method setterMethod) { try { //当使用ResultSet获取某个字段的时候, 如果没有该字段, 会出现SQLException,忽略该异常 String value = rs.getString(field.getName()); if (!"null".equals(value)) { //从ResultSet中获取与该对象属性名一致的字段, 并执行setter方法 setterMethod.invoke(vo, value); } } catch (Exception e) { //忽略异常 } } //根据属性名获得setter方法的方法名 private static String getSetterMethodName(String fieldName) { String begin = fieldName.substring(0, 1).toUpperCase(); String end = fieldName.substring(1, fieldName.length()); String methodName = "set" + begin + end; return methodName; } //相加两个数组 private static Field[] addFields(Field[] f1, Field[] f2) { List l = new ArrayList(); for (Field f : f1) l.add(f); for (Field f : f2) l.add(f); return l.toArray(new Field[f1.length + f2.length]); } } 以上代码中的getDatas方法,遍历参数的ResultSet,将 ResultSet中的某个字段值设置到目标对象中,最后加入到结果集中返回。我们使用了Java的反射来找到字段对应的类属性,再调用setter方法,就可以将字段值设置到具体的对象中。 10.3.2 数据库执行类 数据库执行类保存了数据库连接的相关信息,包括连接IP、用户名、密码等JDBC连接信息,提供一些基本的SQL执行方法,包括SQL的执行、数据库的查询等,并且该类在本系统中只有一个实例。以下是该类的提供的几个基本方法。 代码清单:code\transaction\src\org\crazyit\transaction\jdbc\JDBCExecutor.java: //计算数据总数 public Integer count(String sql) { //利用Statement对象执行参数的sql ResultSet result = stmt.executeQuery(sql); result.next(); Integer count = result.getInt(1); result.close(); return count; } //执行一句查询的sql public ResultSet executeQuery(String sql) { //利用Statement对象执行参数的sql ResultSet result = stmt.executeQuery(sql); return result; } //执行单句INSERT、UPDATE 或 DELETE 语句, 如果执行INSERT时, 返回主键 public int executeUpdate(String sql) { //执行SQL语句 stmt.executeUpdate(sql); //获得主键 ResultSet rs = stmt.getGeneratedKeys(); while(rs.next()) { //返回最后一个主键 result = rs.getInt(1); } rs.close(); return result; } 以上的代码中使用JDBC中的Statement执行SQL语句得到相应的ResultSet对象。 10.3.3 DAO层的基类 新建一个DAO层,让其他的DAO对象都去继续该基类,该基类只提供getDatas和getJDBCExecutor方法,geDatas方法对ResultSet对象进行封装,getJDBCExecutor方法返回JDBC执行类。 代码清单:code\transaction\src\org\crazyit\transaction\dao\impl\BaseDaoImpl.java: public class BaseDaoImpl { //返回JDBCExecutor对象 public JDBCExecutor getJDBCExecutor() { return JDBCExecutor.getJDBCExecutor(); } //根据参数的SQL, 存放结果的集合对象, 和具体的数据库映射对象返回一个集合 public Collection getDatas(String sql, Collection result, Class clazz) { //执行SQL返回ResultSet对象 ResultSet rs = getJDBCExecutor().executeQuery(sql); //对ResultSet进行封装并返回集合 return DataUtil.getDatas(result, rs, clazz); } } 注意以上的黑体代码,使用了数据转换工具类进行数据封装,将ResultSet对象封装成一个集合返回,提供了该方法后,其他的DAO实现类就可以继续这个基类,并使用getDatas方法对数据进行封装。出可以使用getJDBCExecutor方法直接得到JDBC执行对象,并执行相应的SQL语句。 10.3.4 值对象基类 在本系统中,我们使用一个值对象来表示一个数据表,并且该值对象中的属性与数据表中的字段名称一致,就好像我们在开发企业应用时所使用的ORM框架一样,提供一个Java对象与数据库的表进行映射。我们提供一个所有值对象的基类,所有的值对象都需要继续于它。 代码清单:code\transaction\src\org\crazyit\transaction\model\ValueObject.java: public class ValueObject { //ID字段,对应数据库中的ID列 private String ID; } 其他的值对象继承于ValueObject,就意味着该值对象对应的数据库表中必须要有一个ID字段。 到此,在开发中所使用到的各个类都已经准备完成,接下来可以进行功能开发。 10.4 用户管理 从用户管理界面中可以看到,一个用户包括用户名、密码、真实改名与角色,那么在设计数据库的时候,我们可以将这些信息创建一个用户表,用于保存用户记录,另外还需要有一个角色表,用于保存系统中的角色。 10.4.1 设计用户管理的相关对象 创建一个角色对象,在系统中表示用户的角色,角色对象只包括角色名称一个属性,由于本章重点并不是权限管理,因此只提供权限名称作为权限标识。 代码清单:code\transaction\src\org\crazyit\transaction\model\Role.java public class Role extends ValueObject { //角色名称, 如经理, 总监 private String ROLE_NAME; } 接下来设计一个用户对象,表示系统中的一个用户对象,用户对象包括用户名、密码、真实姓名与所属的角色外键,还需要注意的是,因为我们要实现删除用户的功能,删除用户时并不是真实的删除用户的数据,而对该用户的数据进行逻辑删除,这是为了不影响其他业务数据而做的,所以还要提供一个标识属性,标识该用户数据是否被删除。 代码清单:code\transaction\src\org\crazyit\transaction\model\User.java: public class User extends ValueObject { //用户名称 private String USER_NAME; //密码 private String PASS_WD; //用户角色id, 数据库字段 private String ROLE_ID; //用户真实名称 private String REAL_NAME; //是否被删除, 0没有被删除, 1为已经删除 private String IS_DELETE; } 设计了用户的两个对象后,就可以根据这两个对象,创建相应的数据库表,在本章中,如无特别说明,所有的数据表ID均为自动增长(auto_increment)。创建角色表与用户表的SQL语句如下: CREATE TABLE `t_role` ( `ROLE_NAME` varchar(255) NOT NULL, `ID` int(10) NOT NULL auto_increment, PRIMARY KEY (`ID`) ) CREATE TABLE `t_user` ( `ID` int(10) NOT NULL auto_increment, `USER_NAME` varchar(255) NOT NULL, `ROLE_ID` int(10) NOT NULL, `REAL_NAME` varchar(255) default NULL, `IS_DELETE` varchar(255) NOT NULL default '0', `PASS_WD` varchar(255) NOT NULL, PRIMARY KEY (`ID`), KEY `ROLE_ID` (`ROLE_ID`), CONSTRAINT `t_user_ibfk_1` FOREIGN KEY (`ROLE_ID`) REFERENCES `t_role` (`ID`) ON DELETE CASCADE ) 10.4.2 用户登录 新建角色DAO与用户DAO接口,并为其提供实现类,DAO层组件主要负责与数据库进行交互,编写SQL语句让JDBC执行类执行,得到相应的数据后再返回。以下是角色DAO接口定义的方法。 代码清单:code\transaction\src\org\crazyit\transaction\dao\RoleDao.java: public interface RoleDao { /** * 根据ID查找角色 * @param id * @return */ Role find(String id); /** * 查找全部的角色 * @return */ List findRoles(); } 角色DAO接口提供了根据ID查找角色与查找全部角色的功能,以下是该接口实现类的具体实现。 代码清单:code\transaction\src\org\crazyit\transaction\dao\impl\RoleDaoImpl.java: public class RoleDaoImpl extends BaseDaoImpl implements RoleDao { public Role find(String id) { String sql = "select * from T_ROLE ro where ro.id = '" + id + "'"; List result = (List)getDatas(sql, new ArrayList(), Role.class); return result.size() == 1 ? result.get(0) : null; } public List findRoles() { String sql = "select * from T_ROLE"; return (List)getDatas(sql, new ArrayList(), Role.class); } } 在以上代码中,RoleDaoImpl继承于DAO基类:BaseDaoImpl,那么就可以调用基类的两个方法(getDatas与getJDBCExecutor),以上代码只负责用于得到相关的角色对象。 新建用户DAO接口与其实现类,并新建用户业务逻辑接口UserService与其实现类UserServiceImpl,系统中的相关业务逻辑代码都将被放置到业务逻辑层进行处理,与DAO层的实现一样,需要编写一个用户的业务逻辑接口,再为其提供实现。在DAO层与业务逻辑层中,我们都需要提供接口,这样做的话,这些组件的调用者,只需要直接使用接口来调用方法,并不需要去关心这些组件是如何实现的,一旦业务或者DAO层发生变化,也不必去修改调用者的代码。 业务逻辑层是让视图层调用的,因此我们还需要关心这些业务逻辑对象的创建,我们可以为系统提供一个ApplicationContext的对象,来保存这些DAO或者业务逻辑组件的实例,那么在系统的任何地方,都可以轻易的得到这些组件的实例。 代码清单:code\transaction\src\org\crazyit\transaction\util\ApplicationContext.java: public class ApplicationContext { //登录的用户 public static User loginUser; //用户DAO接口 public static UserDao userDao; //角色DAO接口 public static RoleDao roleDao; //角色业务逻辑接口 public static RoleService roleService; //用户业务逻辑接口 public static UserService userService; static { logDao = new LogDaoImpl(); roleDao = new RoleDaoImpl(); roleService = new RoleServiceImpl(roleDao); userDao = new UserDaoImpl(); userService = new UserServiceImpl(userDao, roleDao); } } ApplicationContext负责创建与维护这些DAO组件与业务逻辑组件,使用者只需要使用以下代码,就可以得到某个组件的实例。 ApplicationContext.userService.method; 在UserDao中新建一个findUser方法,用于根据用户名和密码查找具体的某个用户,并在UserService中提供一个login的方法,用来进行用户登录,如果用户可以成功登录,则设置到ApplicationContext中的loginUser,表示正在使用系统的用户,如果没有登录成功,则抛出业务异常。 代码清单:code\transaction\src\org\crazyit\transaction\dao\impl\UserDaoImpl.java: public User findUser(String userName, String passwd) { String sql = "select * from T_USER u where u.USER_NAME = '" + userName + "' and u.PASS_WD = '" + passwd + "' and u.IS_DELETE = '0'"; List users = (List)getDatas(sql, new ArrayList(), User.class); return users.size() == 1 ? users.get(0) : null; } 代码清单:code\transaction\src\org\crazyit\transaction\service\impl\UserServiceImpl.java: public void login(String userName, String passwd) { User user = this.userDao.findUser(userName, passwd); //没有找到用户, 抛出异常 if (user == null) throw new BusinessException("用户名密码错误"); Role role = this.roleDao.find(user.getROLE_ID()); user.setRole(role); ApplicationContext.loginUser = user; } 在登录界面中,就可以直接调用UserService的login方法进行用户登录,并进行异常捕捉。以下是登录界面LoginFrame的部分实现。 代码清单:code\transaction\src\org\crazyit\transaction\ui\LoginFrame.java: //点击确定按钮触发的方法 private void login() { //得到用户名 String userName = this.userName.getText(); //得到密码 String passwd = getPassword(); //进行登录 try { ApplicationContext.userService.login(userName, passwd); this.setVisible(false); MainFrame mf = new MainFrame(); } catch (Exception e) { e.printStackTrace(); ViewUtil.showWarn(e.getMessage(), this); } } 以上的黑体代码中,调用了UserService的login方法进行登录。 10.4.3 查找全部用户 在接口UserDao中定义一个findUsers方法,用于返回系统中全部的用户。 代码清单:code\transaction\src\org\crazyit\transaction\dao\UserDao.java: /** * 查找全部的用户 * @return */ List findUsers(); 在实现findUsers方法的时候,需要注意的是,查询的时候需要加入查询条件,在本章中,用户是可以被逻辑删除的,因此编写SQL语句的时候,需要加入逻辑删除的判定条件。 代码清单:code\transaction\src\org\crazyit\transaction\dao\impl\UserDaoImpl.java: public List findUsers() { String sql = "select * from T_USER u where u.IS_DELETE = '0'"; List users = (List)getDatas(sql, new ArrayList(), User.class); return users; } 在UserService中定义getUsers方法,用于返回全部的系统用户。以下是getUsers方法的具体实现。 代码清单:code\transaction\src\org\crazyit\transaction\service\impl\UserServiceImpl.java: public List getUsers() { List users = this.userDao.findUsers(); for (User u : users) { Role role = this.roleDao.find(u.getROLE_ID()); u.setRole(role); } return users; } 以上代码的黑体部分,使用UserDao与RoleDao来获取数据,需要注意的是,User对象中有一个Role属性,当查出User对象的时候,该属性为null,因此我们需要根据User的ROLE_ID属性去获取相应的Role对象(到数据库中查找)。在视图层中,只需要通过ApplicationContext的userService就可以调用getUsers方法得到全部的系统用户。本章的用户列表是一个JTable的子类,如果需要对用户列表进行渲染,只需要提供一个TableModel即可,以下是用户列表的TableModel的部分实现。 代码清单:code\transaction\src\org\crazyit\transaction\ui\table\UserTableModel.java: //表示本列表的数据集合 private List datas; //返回数据行数 public int getRowCount() { if (this.datas != null) { return this.datas.size(); } return 0; } public String getColumnName(int col) { return columnNames[col]; } public int getColumnCount() { return columnNames.length; } public void setDatas(List datas) { this.datas = datas; } //渲染每一列的数据 public Object getValueAt(int row, int column) { String columnName = this.getColumnName(column); if (this.datas != null) { User user = this.datas.get(row); if (USER_ID.equals(columnName)) { return user.getID(); } else if (USER_NAME.equals(columnName)) { return user.getUSER_NAME(); } else if (REAL_NAME.equals(columnName)) { return user.getREAL_NAME(); } else if (ROLE.equals(columnName)) { return user.getRole().getROLE_NAME(); } } return super.getValueAt(row, column); } 在用户管理界面中只需要调用UserService的getUsers方法就可以得到全部的系统用户,再得到TableModel对象,将用户集合设置到TableModel中即可。 代码清单:code\transaction\src\org\crazyit\transaction\ui\UserPanel.java: List users = ApplicationContext.userService.getUsers(); this.tableModel.setDatas(users); this.dataTable.updateUI(); 这里需要注意的是,无论用户登录还是查找全部用户,都需要加入非逻辑删除的条件判断。 10.4.4 新增用户功能 新增用户,除需要用户名、密码和用户真实姓名外,还需要选择用户的角色。在RoleService中提供一个getRoles方法,用于返回全部的角色,在视图层中,只需要调用该方法即可。以下是创建角色下拉框的代码。 代码清单:code\transaction\src\org\crazyit\transaction\ui\dialog\AddUserDialog.java: //创建角色下拉 private void createRoleSelect() { this.roleSelect.removeAllItems(); List roles = ApplicationContext.roleService.getRoles(); for (Role r : roles) { this.roleSelect.addItem(r); } } 以上代码的黑体部分,调用RoleService的getRoles方法得到全部的角色,具体的效果如图10.10所示。 图10.10 查找全部角色 在这里需要注意的是,如果将Role对象作为下拉框的元素,需要重写Role的toString方法,返回角色名称。从界面中得到用户的各个信息后,就可以在UserService中定义一个addUser方法,对新增的用户进行保存,并在UserDao中提供一个保存用户的方法,调用JDBC执行类来执行插入的SQL语句。 代码清单:code\transaction\src\org\crazyit\transaction\dao\impl\UserDaoImpl.java: public void save(User user) { StringBuffer sql = new StringBuffer("insert into T_USER VALUES (ID, '"); sql.append(user.getUSER_NAME() + "', '") .append(user.getROLE_ID() + "', '") .append(user.getREAL_NAME() + "', '") .append("0', '") .append(user.getPASS_WD() + "')"); getJDBCExecutor().executeUpdate(sql.toString()); } 代码清单:code\transaction\src\org\crazyit\transaction\service\impl\UserServiceImpl.java: public void addUser(User user) { //根据新的用户名去查找, 判断是否存在相同用户名的用户 User u = this.userDao.findUser(user.getUSER_NAME()); if (u != null) throw new BusinessException("该用户名已经存在"); this.userDao.save(user); } 在实现新增用户的业务逻辑时,如果存在相同用户名的用户数据,则需要抛出异常,可以为UserDao加入一个根据用户查找用户对象的方法,如果能找到相应的用户,则表示该用户名已经存在,不可以新增。 10.4.5 删除用户 在本章中,由于用户有可能与某条业务数据绑定(事务),因此不可以随便删除,如果需要删除数据,我们只为其提供逻辑删除,即将用户表的IS_DELETE设置为1,让该数据不会出现在用户管理界面即可。修改数据使用SQL的update语句。以下是UserDaoImpl的实现。 代码清单:code\transaction\src\org\crazyit\transaction\dao\impl\UserDaoImpl.java: public void delete(String id) { StringBuffer sql = new StringBuffer("update T_USER u"); sql.append(" set u.IS_DELETE = '1'") .append(" where u.ID = '" + id + "'"); getJDBCExecutor().executeUpdate(sql.toString()); } 简单的修改用户表的IS_DELETE字段值,再使用JDBC执行类来执行该句SQL即可。 10.4.6 查询用户 用户管理界面中,提供了一个查询用户的功能,操作人输入用户姓名后,系统就会根据用户所输入的信息到数据库中进行模糊查询。由于我们使用的是MySQL数据库,因此可以使用MySQL的like关键字进行模糊查询。以下是UserDaoImpl的查询方法的实现。 代码清单:code\transaction\src\org\crazyit\transaction\dao\impl\UserDaoImpl.java: public List query(String realName) { String sql = "select * from T_USER u where u.REAL_NAME like '%" + realName + "%' and u.IS_DELETE = '0'"; List users = (List)getDatas(sql, new ArrayList(), User.class); return users; } 以上代码的黑体部分,使用了like关键字进行查询,例如要查询用户姓名含有“java”字符串的数据时,就可以使用“like %java%”进行查询。 10.5 事务管理 事务管理模块是由企业的管理人员进行操作的,在该模块中,可以新建事务并将事务分发到某个下属员工中,还可以查看自己发起的事务状态与流程,如果发现系统中有些事务延后,可以使用模块中的催办功能,让负责该事务的员工看到,该事务需要紧急处理。当管理者发现新建了一些没有意义的事务时,可以将该事务置为无效,这样事务处理人就不必为该事务作出没有必要的处理。 10.5.1 设计事务对象 在10.4.1中,我们已经设计了角色与用户对象,并根据这些对象创建表结构,那么在设计事务对象的时候,我们也可以采用这样的方式进行设计。从10.2.6的新建事务界面中可以看出,一个事务包含的有标题、内容、完成时间、处理人和事务发起人,除了这些信息外,事务还需要保存事务的完成时间、创建时间、事务状态、是否需要紧急处理等信息。创建一个Transaction的类,继承ValueObject,Transaction对象的属性如下。 代码清单:code\transaction\src\org\crazyit\transaction\model\Transaction.java: public class Transaction extends ValueObject { //事务标题 private String TS_TITLE; //事务内容 private String TS_CONTENT; //目标完成日期 private String TS_TARGETDATE; //实际完成日期 private String TS_FACTDATE; //开始日期(创建日期) private String TS_CREATEDATE; //发起人ID private String INITIATOR_ID; //当前处理人ID private String HANDLER_ID; //上一个处理人ID private String PRE_HANDLER_ID; //事务状态 private String TS_STATE; //是否需要紧急处理, 0为不用, 1需要紧急处理 private String IS_HURRY; } 除了事务的最基本的几个属性外,需要注意的是当前处理人ID与上一个处理人ID,当前处理人是指现在正在执行事务的用户。由于事务可以在用户之间进行转发,因此就存在当前处理人与前一个处理人的问题,为了以后的可扩展性,我们可以建立多一个关联来表示这种关系。以上的Transaction属性都需要保存到数据库中,根据我们所设计的这些属性,创建事务相应的表。 同样地,也为事务对象创建它的DAO对象与业务逻辑对象:TransactionDao、TransactionService。也需要为这两个接口添加实现类。在本小节中,由于只是管理者进行事务管理,并不需要实现其他功能(例如转发),因此不需要设计其他相关的对象。 10.5.2 根据发起人查找事务 在事务管理中,事务的管理者可以看到自己发起的事务并对其进行跟踪,当管理者登录到系统中,并进入事务管理时,就需要到数据库中查找该用户所发起的事务。在设计事务对象的时候,就已经提供了一个INITIATOR_ID的属性,表示发起人的ID,那么我们就可以根据登录用户的ID去数据库中进行查找。 为TransactionDao加入查询方法,该方法的具体实现如下。 代码清单:code\transaction\src\org\crazyit\transaction\dao\impl\TransactionDaoImpl.java: public List findInitiatorTransactions(String state, String userId) { StringBuffer sql = new StringBuffer("select * from T_TRANSACTION ts"); sql.append(" where ts.INITIATOR_ID = '") .append(userId + "'") .append(" and ts.TS_STATE = '") .append(state + "' order by ts.IS_HURRY desc"); List result = (List
本文档为【疯狂java实战演义_第10章_事务跟踪系统】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_954804
暂无简介~
格式:doc
大小:456KB
软件:Word
页数:35
分类:理学
上传时间:2011-05-08
浏览量:11