【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     }
相關文章
相關標籤/搜索