之前SSH框架已经搭建完毕,现在进行实体类的分析和Base类的书写。Base类是抽象类,专门用于继承。

一、实体类关系分析

  既然是数据采集系统,首先调查实体(Survey)是一定要有的,一个调查有多个页面(Page),一个页面有多个问题(Question),所以还要有页面和问题实体。参与完成调查之后一定还会生成若干个答案,所以还有答案实体(Answer),当然还有参与的用户(User),管理员是特殊的User,只需要登陆的时候进行判断即可。

  分析实体类型是比较简单的,最重要的是设计,怎样设计才能满足调查中所需要的各种字段要求?各个实体之间是否有关系,如果有关系是否需要做双向关联(hibernate配置文件中声明)?。

  首先从User实体开始分析,一个用户可以参与多个调查,一个调查可以被多个用户参与,所以User和Survey实体之间是典型的多对多关系。既然有有关系了,那么是否需要做双向关联?我们经常做的是根据User对象拿到该User对象拥有的所有Survey,我们基本上不会用到根据Survey对象取得User对象,所以我们只需要做User到Survey的多对多映射关系即可。以上的分析是错误的。这里的User和Survey之间的关系是创建的关系,而不是参与调查的关系。所以一个用户能够创建多个调查,但是一个调查只能被一个用户创建,所以调查和用户之间是多对一关系。虽然我们会通过User对象获取Survey对象集合,但是我们并不会经常这么做,而且这么做有一个致命的缺点,那就是会增加Session的存储压力。为了减小Session的存储压力,我们只做Survey到User的多对一单向关联,不做User到Survey的多对一关联。

  Survey实体和Page以及User均有关系,但是不做到User的多对多关系的映射。Survey和Page之间是一对多的关系,一个页面只能出现在一个Survey中,但是一个Survey中能够有多个Page。既然两者有关系,是需要做两者的双向关联关系还是单向关联关系?我们会根据Survey对象获取该对象的所有Page,也会根据该Page获取该页面属于哪一个Survey对象,所以我们需要做双向关联关系,即做Survey到Page的一对多映射和做Page到Survey的多对一映射。

  Page实体和Question同理,我们需要做Page到Quesiton的一对多映射,也需要做Question到Page的多对一映射。

  Answer实体暂时不作考虑。

二、实体属性分析

  1.Question分析(最复杂)

    为了能够使用该Question对象保存住所有九种类型的选项,Quesiton中的属性能够表示出这九种类型。

    九种类型的题型(排列顺序不能改变,因为需要通过该位置获取问题的类别):

      第一类:非矩阵式横向单选按钮、非矩阵式纵向单选按钮、非矩阵式横向复选按钮、非矩阵式纵向复选按钮

      第二类:非矩阵式下拉列表

      第三类:非矩阵式文本框

      第四类:矩阵式单选按钮、矩阵式复选按钮

      第五类:矩阵式下拉列表

  1.   private transient Integer questionId; //问题的ID
  2. /**
  3. * 题型分为0-8一共九种类型
  4. */
  5. private int questionType; //问题的题型
  6. private String title; //问题的标题
  7. private String optionText; //问题的选项
  8. private String[]optionTextArr; //问题选项的集合
  9.  
  10. private boolean other; //其他项
  11. //其他项可能是无、文本框、下拉列表框
  12. private String otherType; //其他项的样式
  13. private String otherSelectOptions; //其他项如果是下拉列表框的话使用该项作为内容
  14. private String[] otherSelectOptionArr; //该字段对应着其他项是多选框的情况,这里存放着拆分之后的字符串数组
  15.  
  16. private String matrixRowTitles; //矩阵式行标题集
  17. private String[] matrixRowTitleArr; //矩阵式行标题集数组
  18. private String matrixColTitles; //矩阵式列标题集
  19. private String[] matrixColTitleArr; //矩阵式列标题集数组
  20. private String matrixSelectOptions; //矩阵式下拉选项集
  21. private String []matrixSelectOptionArr; //矩阵式下拉列表
  22.  
  23. //Question和Page之间是多对一的关系
  24. private Page page;

      对于每一个问题来说,不可能每个属性都用的到,但是必须要这么写,否则就需要针对每一种提醒设计一种Question实体,那样就麻烦了。

  2.Page

  1. private transient Integer pageId; //页面id
  2. private String title="未命名"; //页面标题
  3. private String description; //页面描述
  4.  
  5. //page和调查之间是多对一的关系
  6. private transient Survey survey;
  7. //page和Question之间是一对多的关系
  8. private Set<Question> questions=new HashSet<Question>();
  9. private float orderNo; //排序的优先级,默认值和pageId相同

    需要说明一个字段是orderNo,该字段的用处是排序,默认值和pageId相同,这个将会在以后的复制/移动页的功能中使用到。

  3.Survey分析(复杂)

  1. private Integer surveyId; //对应着调查id
  2. private String title="未命名"; //对应着调查名称
  3. private String preText="上一页"; //对应着翻页的上一个提示
  4. private String nextText="下一页"; //对应着下一页的提示
  5. private String exitText="退出"; //对应着退出的提示
  6. private String doneText="完成"; //对应着完成的提示文本
  7. private Date createDate=new Date(); //对应着创建的日期
  8. private String logoPath; //使用该字段保存图标的位置,保存的是相对位置
  9. //调查和用户之间是多对一的关系
  10. private User user;
  11. //调查和Page之间是一对多的关系
  12. private transient Set<Page>pages=new HashSet<Page>();
  13.  
  14. //添加一个调查是否可用的字段,表示打开或者关闭调查
  15. private boolean closed;
  16.  
  17. /**
  18. * TODO 在数据库库中没有定义,但是需要在配置文件中定义并带到前端页面中使用
  19. */
  20. private float maxOrderNo; //最小页序
  21. private float minOrderNo; //最大页序
  22.  
  23. //定义几个常量,方便判断是哪种类型的提交
  24. private String submit_next="下一页";
  25. private String submit_pre="上一页";
  26. private String submit_done="提交";
  27. private String submit_exit="退出";

  4.Use类分析

  1. private Integer userId; //用户id
  2. private String password; //用户密码
  3. private String nickName; //用户昵称
  4. private String email; //用户邮件
  5. private Date registerDate; //用户注册日期
  6. private Set<Role>roles;
  7. private Boolean superAdmin; //判定是否是超级管理员的标识字段
  8. private long[]rightSum; //进行权限判定的关键,注意这里一定要使用基本数据类型,否则会有问题,因为包装类型的默认值不是0,是null

    该类在项目初期中只用到了一部分属性,像是基本的userId、password等,剩下的roles、superAdmin、rightSum在权限管理模块中会使用到。

  5.hibernate映射文件略。

三、Base类书写。

  1.BaseDao书写

    针对每一个实体,我们都需要写一个DAO操作对应的数据库中的表,将所有的DAO中的公共方法抽象出来放到一个抽象类中是一个比较好的方法,这样能够极大的重用代码。当然,我们还需要使用一个接口对该抽象类进行规范。

    DAO接口规范:

  1. package com.kdyzm.dao.base;
  2.  
  3. import java.io.Serializable;
  4. import java.util.Collection;
  5. import java.util.List;
  6.  
  7. public interface BaseDao <T>{
  8. //写操作
  9. public void saveEntity(T t);
  10. public void updateEntity(T t);
  11. public void saveOrUpdateEntity(T t);
  12. public void deleteEntiry(T t);
  13.  
  14. //按照hql批处理
  15. public void batchEntityByHql(String hql,Object ...objects);
  16.  
  17. //查询方法
  18. public T getEntityById(Serializable id);
  19. public T loadEntiryById(Serializable id);
  20. public List<T> findEntityByHQL(String hql,Object ...objects);
  21. public Object findUniqueResult(String hql,Object ...objects);
  22. public Collection<T> findAllEntities();
  23. public void executeSql(String sql,Object ...objects);
  24. public Collection<T> findAllEntitiesBySql(String sql,Object ...objects);
  25. }

    实现类(抽象):

  1. package com.kdyzm.dao.base.impl;
  2.  
  3. import java.io.Serializable;
  4. import java.lang.reflect.ParameterizedType;
  5. import java.util.Collection;
  6. import java.util.List;
  7.  
  8. import javax.annotation.Resource;
  9.  
  10. import org.hibernate.Query;
  11. import org.hibernate.SQLQuery;
  12. import org.hibernate.SessionFactory;
  13.  
  14. import com.kdyzm.dao.base.BaseDao;
  15. /***
  16. * BaseDaoImpl类必须是抽象类,实现已经定义好的接口
  17. * @author kdyzm
  18. *
  19. * @param <T>
  20. */
  21. @SuppressWarnings("unchecked")
  22. public abstract class BaseDaoImpl<T> implements BaseDao<T> {
  23. //手下需要两个成员变量,这两个成员变量的赋值,一个是通过spring容器管理,一个是通过泛型动态获取
  24. @Resource(name="sessionFactory")
  25. public SessionFactory sessionFactory;
  26. private Class<T> clazz;
  27.  
  28. //在默认构造方法中调用相关程序获取真实的泛型类型
  29. public BaseDaoImpl() {
  30. ParameterizedType parameterizedType=(ParameterizedType) this.getClass().getGenericSuperclass();
  31. clazz=(Class<T>) parameterizedType.getActualTypeArguments()[0];
  32. }
  33. @Override
  34. public void saveEntity(T t) {
  35. System.out.println("将要保存"+t);
  36. this.sessionFactory.getCurrentSession().save(t);
  37. }
  38.  
  39. @Override
  40. public void updateEntity(T t) {
  41. this.sessionFactory.getCurrentSession().update(t);
  42. }
  43.  
  44. @Override
  45. public void saveOrUpdateEntity(T t) {
  46. this.sessionFactory.getCurrentSession().saveOrUpdate(t);
  47. }
  48.  
  49. @Override
  50. public void deleteEntiry(T t) {
  51. this.sessionFactory.getCurrentSession().delete(t);
  52. }
  53.  
  54. //批量处理更新的方法重点是使用Query对象
  55. @Override
  56. public void batchEntityByHql(String hql, Object... objects) {
  57. Query query=this.sessionFactory.getCurrentSession().createQuery(hql);
  58. for(int i=0;i<objects.length;i++){
  59. query.setParameter(i, objects[i]);
  60. }
  61. query.executeUpdate();
  62. }
  63.  
  64. @Override
  65. public T getEntityById(Serializable id) {
  66. return (T) this.sessionFactory.getCurrentSession().get(clazz,id);
  67. }
  68.  
  69. @Override
  70. public T loadEntiryById(Serializable id) {
  71. return (T) this.sessionFactory.getCurrentSession().load(clazz, id);
  72. }
  73.  
  74. @Override
  75. public List<T> findEntityByHQL(String hql, Object... objects) {
  76. Query query=this.sessionFactory.getCurrentSession().createQuery(hql);
  77. for(int i=0;i<objects.length;i++){
  78. query.setParameter(i, objects[i]);
  79. }
  80. return query.list();
  81. }
  82. @Override
  83. public Object findUniqueResult(String hql, Object... objects) {
  84. Query query=this.sessionFactory.getCurrentSession().createQuery(hql);
  85. for(int i=0;i<objects.length;i++){
  86. query.setParameter(i, objects[i]);
  87. }
  88. return query.uniqueResult();
  89. }
  90. @Override
  91. public Collection<T> findAllEntities(){
  92. String hql="from "+clazz.getSimpleName();
  93. return this.sessionFactory.getCurrentSession().createQuery(hql).list();
  94. }
  95. //直接执行sql语句的方法
  96. @Override
  97. public void executeSql(String sql, Object... objects) {
  98. SQLQuery sqlQuery=this.sessionFactory.getCurrentSession().createSQLQuery(sql);
  99. for(int i=0;i<objects.length;i++){
  100. sqlQuery.setParameter(i, objects[i]);
  101. }
  102. sqlQuery.executeUpdate();
  103. }
  104. //根据sql语句得到List集合的方法
  105. @Override
  106. public Collection<T> findAllEntitiesBySql(String sql, Object... objects) {
  107. SQLQuery sqlQuery=this.sessionFactory.getCurrentSession().createSQLQuery(sql);
  108. for(int i=0;i<objects.length;i++){
  109. sqlQuery.setParameter(i, objects[i]);
  110. }
  111. sqlQuery.addEntity(clazz);
  112. return sqlQuery.list();
  113. }
  114. }

      实现类需要解决的问题:实现所有的公共方法是其功能要求,想要实现这一点,就必须解决一个最重要的问题,如何获取泛型类型,所有的DAO都会提供一个泛型给父类,即BaseDaoImpl,父类必须知道该类型是什么,在构造方法中获取该类型是最合适的:

  1. //在默认构造方法中调用相关程序获取真实的泛型类型
  2. public BaseDaoImpl() {
  3. ParameterizedType parameterizedType=(ParameterizedType) this.getClass().getGenericSuperclass();
  4. clazz=(Class<T>) parameterizedType.getActualTypeArguments()[0];
  5. }

    这样clazz对象就保存到了类中的成员变量,其它方法就能够直接使用该对象了。

  2.BaseService书写

    BaseService接口中的方法和DAO中的方法相同,实现类中直接调用DAO中的方法

  1. package com.kdyzm.service.base;
  2.  
  3. import java.io.Serializable;
  4. import java.util.Collection;
  5. import java.util.List;
  6.  
  7. public interface BaseService<T> {
  8. //写操作
  9. public void saveEntity(T t);
  10. public void updateEntity(T t);
  11. public void saveOrUpdateEntity(T t);
  12. public void deleteEntiry(T t);
  13.  
  14. //按照hql批处理
  15. public void batchEntityByHql(String hql,Object ...objects);
  16.  
  17. //查询方法
  18. public T getEntityById(Serializable id);
  19. public T loadEntiryById(Serializable id);
  20. public List<T> findEntityByHQL(String hql,Object ...objects);
  21. public Collection<T> findAllEntities();
  22.  
  23. public void executeSql(String sql,Object ...objects);
  24. public Collection<T> findAllEntitiesBySQl(String sql,Object ...objects);
  25. }

com.kdyzm.service.base.BaseService

    BaseServiceImpl实现:实现类中有一个BaseDao<T>类型的成员变量,所有的DAO都实现了BaseDao接口,所以直接使用该接口来引用子类对象是可以的,但是拿到泛型的方式并不是DAO中的实现方式,而是直接由实现类通过set方法传递过来。

  1. public BaseDao<T> baseDao;
  2. public void setBaseDao(BaseDao<T> baseDao) {
  3. this.baseDao = baseDao;
  4. }

四、针对各种DAO和Service的实现类略。

五、测试

  1.实现加入log4j的配置文件到classpath,方便查看控制台输出。

  1. ### direct log messages to stdout ###
  2. log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  3. log4j.appender.stdout.Target=System.out
  4. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
  5. log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
  6.  
  7. ### direct messages to file hibernate.log ###
  8. #log4j.appender.file=org.apache.log4j.FileAppender
  9. #log4j.appender.file.File=hibernate.log
  10. #log4j.appender.file.layout=org.apache.log4j.PatternLayout
  11. #log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
  12.  
  13. ### set log levels - for more verbose logging change 'info' to 'debug' ###
  14.  
  15. log4j.rootLogger=warn, stdout
  16.  
  17. #log4j.logger.org.hibernate=info
  18. log4j.logger.org.hibernate=info
  19.  
  20. ### log HQL query parser activity
  21. #log4j.logger.org.hibernate.hql.ast.AST=debug
  22.  
  23. ### log just the SQL
  24. #log4j.logger.org.hibernate.SQL=debug
  25.  
  26. ### log JDBC bind parameters ###
  27. log4j.logger.org.hibernate.type=info
  28. #log4j.logger.org.hibernate.type=debug
  29.  
  30. ### log schema export/update ###
  31. log4j.logger.org.hibernate.tool.hbm2ddl=debug
  32.  
  33. ### log HQL parse trees
  34. #log4j.logger.org.hibernate.hql=debug
  35.  
  36. ### log cache activity ###
  37. #log4j.logger.org.hibernate.cache=debug
  38.  
  39. ### log transaction activity
  40. #log4j.logger.org.hibernate.transaction=debug
  41.  
  42. ### log JDBC resource acquisition
  43. #log4j.logger.org.hibernate.jdbc=debug
  44.  
  45. ### enable the following line if you want to track down connection ###
  46. ### leakages when using DriverManagerConnectionProvider ###
  47. #log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace

log4j.properties

  2.测试类

  1. public class TestUserService {
  2. private static ApplicationContext ac = null ;
  3.  
  4. @BeforeClass
  5. public static void iniAC(){
  6. ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
  7. }
  8.  
  9. @Test
  10. public void insertUser(){
  11. UserService us = (UserService) ac.getBean("userService");
  12. User u = new User();
  13. u.setEmail("kdyzm@foxmail.com");
  14. u.setPassword("123456");
  15. us.saveEntity(u);
  16. }
  17. }

  

【Java EE 学习 69 下】【数据采集系统第一天】【实体类分析和Base类书写】的更多相关文章

  1. 【Java EE 学习 69 中】【数据采集系统第一天】【SSH框架搭建】

    经过23天的艰苦斗争,终于搞定了数据采集系统~徐培成老师很厉害啊,明明只是用了10天就搞定的项目我却做了23天,还是模仿的...呵呵,算了,总之最后总算是完成了,现在该好好整理该项目了. 第一天的内容 ...

  2. 【Java EE 学习 74 下】【数据采集系统第六天】【使用Jfreechart的统计图实现】【将JFreechart整合到项目中】

    之前说了JFreechart的基本使用方法,包括生成饼图.柱状统计图和折线统计图的方法.现在需要将其整合到数据采集系统中根据调查结果生成三种不同的统计图. 一.统计模型的分析和设计 实现统计图显示的流 ...

  3. 【Java EE 学习 67 下】【OA项目练习】【SSH整合JBPM工作流】【JBPM项目实战】

    一.SSH整合JBPM JBPM基础见http://www.cnblogs.com/kuangdaoyizhimei/p/4981551.html 现在将要实现SSH和JBPM的整合. 1.添加jar ...

  4. 【Java EE 学习 77 下】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】

    之前说过,如果一个数据库中要存储的数据量整体比较小,但是其中一个表存储的数据比较多,比如日志表,这时候就要考虑分表存储了:但是如果一个数据库整体存储的容量就比较大,该怎么办呢?这时候就需要考虑分库了, ...

  5. 【Java EE 学习 72 下】【数据采集系统第四天】【移动/复制页分析】【使用串行化技术实现深度复制】

    一.移动.复制页的逻辑实现 移动.复制页的功能是在设计调查页面的时候需要实现的功能.规则是如果在同一个调查中的话就是移动,如果是在不同调查中的就是复制. 无论是移动还是复制,都需要注意一个问题,那就是 ...

  6. 【Java EE 学习 70 下】【数据采集系统第二天】【Action中User注入】【设计调查页面】【Action中模型赋值问题】【编辑调查】

    一.Action中User注入问题 Action中可能会经常用到已经登陆的User对象,如果每次都从Session中拿会显得非常繁琐.可以想一种方法,当Action想要获取User对象的时候直接使用, ...

  7. 【Java EE 学习 75 下】【数据采集系统第七天】【二进制运算实现权限管理】【使用反射初始化权限表】【权限捕获拦截器动态添加权限】

    一.使用反射动态添加权限 在该系统中,我使用struts2的时候非常规范,访问的Action的形式都是"ActionClassName_MethodName.action?参数列表" ...

  8. 【Java EE 学习 71 下】【数据采集系统第三天】【分析答案实体】【删除问题】【删除页面】【删除调查】【清除调查】【打开/关闭调查】

    一.分析答案实体 分析答案实体主要涉及到的还是设计上的问题,技术点几乎是没有的.首先需要确定一下答案的格式才能最终确定答案实体中需要有哪些属性. 答案格式的设计是十分重要的,现设计格式如下: 在表单中 ...

  9. 【Java EE 学习 78 下】【数据采集系统第十天】【数据采集系统完成】

    一.项目源代码地址 二.项目演示

随机推荐

  1. Net中对Object的定义

    如果你问一个.Net程序员什么是Object,他可能会信誓旦旦的告诉你"Object还不简单吗,就是所有类型的基类"这个答案是对的,但是不足以说明Object真正是什么 好在HTM ...

  2. Jmeter响应内容为文件

    最近测试一个接口是文档转换的接口,比如说把rtf文件转换为PDF,这样的接口调用通过结果树只能查看接口响应是否成功,但是看不到转换后的文档.通过Jmeter监听中的Save Responses to  ...

  3. MyEclipse部署web项目到Tomcat出现An internal error occurred during: "Launching on Tomcat 7.x"的问题

    如果出现了上述的错误按照如下的3个步骤解决:1.首先关闭MyEclipse工作空间.2.然后删除工作空间下的文件."MyEclipse10\workspace.metadata.plugin ...

  4. linux中rz中的-e选项

    linux shell rz和sz是终端下常用的文件传输命令,rz和sz通过shell被调用,其中rz用于从启用终端的系统上传文件到目标系统(终端登录的目标系统), 这里不过多介绍这些命令,只是记录一 ...

  5. sublime text 3 3083 注册码

    亲试,可用! —– BEGIN LICENSE —– Andrew Weber Single User License EA7E-855605 813A03DD 5E4AD9E6 6C0EEB94 B ...

  6. JAVA语法基础作业——动手动脑以及课后实验性问题 (八)

    一.动手动脑 运行AboutException.java示例,了解Java中实现异常处理的基础知识. 1)源代码 import javax.swing.*; class AboutException ...

  7. 决策树-ID3

    id3:无法直接处理数值型数据,可以通过量化方法将数值型数据处理成标称型数据,但涉及太多特征划分,不建议 决策树:的最大优点在于可以给出数据的内在含义,数据形式非常容易理解: 决策树介绍:决策树分类器 ...

  8. EBS提交请求出现REP-3000错误

    在AIX上利用并发请求提交报表的時候,出现如下错误:REP-3000: Internal error starting Oracle Toolkit.这是因为Report Server需要X-Wind ...

  9. MRC迁移ARC之__block

    今日帮着同事把老项目从MRC迁移至ARC,大部分工作无非是删除release,[super dealloc]等方法,只要关闭了MRC编译选项后,编译器能自动帮你检查,block就有一些不一样了,发现许 ...

  10. .net MVC中异常日志

    在日常工作中,我们有些项目可能进入了维护期,但是项目可能存在一些潜伏较深的bug导致我们在测试阶段并未发现,那么错误日志记录为我们的项目维护起着重要的作用.记录系统日志的方法如下 1.在系统根目录建立 ...