【Java EE 学习 69 下】【数据采集系统第一天】【实体类分析和Base类书写】

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

1、实体类关系分析java

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

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

  首先从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的多对一映射。apache

  Page实体和Question同理,咱们须要作Page到Quesiton的一对多映射,也须要作Question到Page的多对一映射。数组

  Answer实体暂时不做考虑。session

2、实体属性分析app

  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

    private transient Integer pageId;            //页面id
    private String title="未命名";        //页面标题
    private String description;    //页面描述
    
    //page和调查之间是多对一的关系
    private transient Survey survey;
    //page和Question之间是一对多的关系
    private Set<Question> questions=new HashSet<Question>();
    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映射文件略。

3、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,父类必须知道该类型是什么,在构造方法中获取该类型是最合适的:

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

    这样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方法传递过来。

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

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

5、测试

  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     }
相关文章
相关标签/搜索