论述篇
系统中将会普遍用到很多类型、状态,如申请状态、性别、民族、单位性质……等等,这些状态没有使用单独的表到一一定义和记录。
解决办法一般会有:每一种类型一个表;在程序中到处写;使用常量静态类;单表保存所有类型;等等
*〉如果为每一种类型定义一个表,定义时直接维护没有一个表,使用时只对这个表来查询。
优点:维护每个类型的值都十分容易,查询速度也比较快
缺点:数据库的表的数量讲会激增,导致使用与维护上的不方便。
*〉在程序中到处写,录入时直接在页面上列出类型中所有值提供选择,显示时逐一判断。
优点:运行效率可能是最高的
缺点:维护工作几乎是异常艰辛的。
*〉使用常量静态类,把这些类型定义为Map,写在一个类里面,并且提供getList(type)方法和getTitle(type,id)方法。
优点:运行效率也会相当的高
缺点:一旦程序发布之后,临时需要新增、修改某些类型的值,又得找到源码重新编译发布。
*〉使用单表保存所有的类型,定义一个读写类,和一个缓冲类
优点:可随时维护,表的数量只有一个
缺点:表里面的数据包含了所有的类型,查询效率可能较低
最终我们确定使用“使用单表保存所有的类型”这一种方法,使用缓冲类来一次加载所有的类型来解决查询查询效率问题。当类型被更新时,再刷新缓冲。
设计篇
一、物理结构
create table oa_typeall (
typename varchar(64) not null,
typeid varchar(32) not null,
typetitle varchar(255) null,
typedesc varchar(32) null,
typeparent varchar(32) null,
constraint pk_typeall primary key (typename,typeid)
);
各个属性说明
typename 类型名称,如民族、申请状态、单位类型等等
typeid 类型标识, 如N, F, D, 0, 1, 2...
typetitle 类型标题, 如汉族、已审批、已通过、集体企业、民营企业等等
typedesc 类型描述
typeparent 类型的上级, 如民营企业的上级是集体企业
二、命名约定
*> typename
为了避免由于数据库编码问题导致查询出错,typename本应设计为存储中文名称的,
现在改为英文名称,使用词典查询最为恰当的单词,如果超过两个单词,中间使用
下划线分割。所有字母要求大写。
如:行业性质 INDUSTRY, 办公用品申请状态OFFICIAL_THINGS_APPLY_STATUS
在确定一个类型的名称前,需要向项目负责人申请一个恰当名字,并且备案。
*> typeid
一般简单在各个表中使用char(1)就可以了,但是这里为了使用更多的需求,所以定义了
32位的字符。
如: N - 正常 A - 异常
01 - 汉族 02 - 满族 03-...
AD - 广告 BULLTINE - 公告 NEWS - 新闻
*>typetitle
这个就是要显示的中文名称,如正常、汉族、广告等等
*>typedesc
由于typename使用了英文,可能导致阅读上的困难,因此在这里可以加入对typename的描述。
如果该类型比较难理解,也可以加入更加详细的描述文字。
*>typeparent
针对某些特定的类型,有显示形式或者统计上的需要,因此设计上要实的这个表可以存储
这个类型的树形层次关系。
只记录类型的上级, 如民营企业的上级是集体企业, 中专的上级是中学,中专、中技的上级
也是中学。
三、存储格式
insert into oa_typeall (typename,typeid,typetitle,typedesc,typeparent)
values ('DEGREE','12','博士','文化程度',null);
insert into oa_typeall (typename,typeid,typetitle,typedesc,typeparent)
values ('DEGREE','11','硕士','文化程度',null);
insert into oa_typeall (typename,typeid,typetitle,typedesc,typeparent)
values ('OFFICIAL_THINGS_APPLY_STATUS','N','未审批','办公用品申请状态',null);
insert into oa_typeall (typename,typeid,typetitle,typedesc,typeparent)
values ('OFFICIAL_THINGS_APPLY_STATUS','Y','已审批','办公用品申请状态',null);
四、维护
五、使用
5.1 定义类 TypeAll
* 缓冲池
* 装载服务
* 初始化方法
* 刷新方法
* 获取列表方法
* 标识翻译成为标题的方法
*> 缓冲池
定义一个HashTable的变量,key=typename, value=Map(typeid, typetitle)
* 装载服务
通过Spring注入读取类型列表的Service事例,访问这个事例的getTypeAll, 返回
类型的List, List每一项是一个字符串数组, 长度为3, 一次是
[0] typename
[1] typeid
[2] typetitle
* 初始化方法
调用装载服务获得类型列表, 把数组的内容写入缓冲池.
* 刷新方法
清空缓冲池, 重新调用初始化方法
* 获取列表方法
根据输入参数typename, 获取Map列表, Map(typeid, typetitle)
对于jsp而言, 根据需要扩展两个方法
1.获取HTML的SELECT的OPTIONS代码
输出<option value='..'>..</option>...
2.获取HTML的RADIO代码
输出<radio name='..' value='..'/><radio../>...
在扩展方法中,根据输入参数defaultVal, 在输入时默认选中一个选项中的值
输出<option value='..'>..</option>...
<option value='defaultVal' selected>..</option>...
对于jsf而言,则需要在每一个用到下拉列表或者单选列表的Form中定义SelectItem[]的get方法,返回指定的同一类型的选项。
* 标识翻译成为标题的方法
根据输入参数typename, 获取Map列表
根据输入参数typeid, 从Map中获取typetitle
输出typetitle
对于jsf而言,TypeAll类提供一个返回Map的方法getTypeItems(typename)来返回指定类型的key-value对。
而FormBean则提供getDegrees方法来调用getTypeItems获得Map,使得在jsf页面上可以使用#{typeall.degrees['myobj.degree']取得typetitle值。
6. 标签
对于JSP, 为了更好的在页面上使用TypeAll, 我们可以自定义标签
<select name="mydegree" style="..">
<typeall:options('DEGREE',null)>
</select>
<typeall:radios('OFFICIAL_THINGS_APPLY_STATUS','N')>
对于JSF,则可以使用<h:selectOneMenu>或者<h:selectOneRadio>来实现。
实现篇
一、创建数据库 oa_typeall
二、编写Pojo和hbm.xml
三、编写Dao接口和实现com.gdie.oa.dao.hibernate.other.OaTypeallDaoHibernate
四、编写Service接口和实现com.gdie.oa.service.impl.other.TypeAllManagerImpl
五、编写JSF的BackingBean, com.gdie.oa.webapp.action.TypeAll
六、装配Spring, 把Dao注入Manager, 再把Manager注入BackingBean
七、配置faces-config.xml, 定义TypeAll为全局Bean
<managed-bean>
<managed-bean-name>typeall</managed-bean-name>
<managed-bean-class>
com.gdie.oa.webapp.action.TypeAll
</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
八、在其他的BackingBean中使用
假设您当前的BackingBean(UserForm)需要使用到一个“文化程度”的下拉框,那么就在你的这个UserForm中定义这样一个get方法,指定要通用类型"DEGREE":
public SelectItem[] getDegreeItems(){
TypeAll typeall = new TypeAll();
SelectItem[] list = typeall.getSelectItem("DEGREE");
System.out.println(list.toString());
return list;
}
九、在jsf页面上不使用TypeAll, 而是使用UserForm,如:
<h:selectOneMenu value="02">
<f:selectItems value="#{userForm.degreeItems}" />
</h:selectOneMenu>
十、如果要翻译类型标示为中文标题,现在考虑在Model里面做。即在OaUser.java中增加方法:
public String getDegreeTypeTitle() {
return TypeAll.getTypetitle("DEGREE", this.degree);
}
那么你在List输出的时候,就不要打印oaUser.degree, 而是要打印oaUser.degreeTypeTitle