1. 程式人生 > >SSM入門:徹底弄懂實體層entity/POJO

SSM入門:徹底弄懂實體層entity/POJO

一.基礎實體類部分:BaseEntity<T>

@SupTreeList
又定義一個抽象類BaseEntity,該抽象類實現介面Serializable
public abstract class BaseEntity<T> implements Serializable{
    private static final long serialVersionUID = 1L;
   

//先記住id屬性,這是最重要的
    protected String id;
  

 //這個五個屬性先忽略
    protected User currentUser;
    protected Page<T> page;
    protected Map<String,String> sqlMap;
    protected Map<String,List<Object>> inSqlMap;
    protected boolean isNewRecord = flase;
   

//再知道這裡的三個常量屬性:DEL_FLAG_NORMAL,DEL_FLAG_DELETE,DEL_FLAG_AUDIT
    public static final String DEL_FLAG_NORMAL = "0";
    public static final String DEL_FLAG_DELETE = "1";
    public static final String DEL_FLAG_AUDIT = "2";

 //定義無參構造方法:BaseEntity()
      在何時呼叫?在哪裡呼叫?呼叫後做了什麼?
    public BaseEntity(){}

//定義有參構造方法:BaseEntity(String id)
      在何時呼叫?在哪裡呼叫?呼叫後做什麼?
    public BaseEntity(String id){
      this();//呼叫無參構造方法!為什麼在這裡呼叫呢?
      this.id = id;
    }

 //id屬性的getter方法getId():多了1個註解,問題:註解做了什麼?
    @SupCol(isUnique="true",isHide="true")
    public String getId(){
        return this.id;
    }
   

//id屬性的setter方法setId():正常
    public void setId(String id){
        this.id = id;
    }
   
  

 //currentUser屬性的getter方法:getCurrentUser():1.多了兩個註解;2.與一般的setter不同,不是直接返回,而是初始化之後再返回!
    //兩種返回的區別在哪裡
    @JsonIgnore
    @XmlTransient
    public User getCurrentUser(){
        //先忽略這個程式碼:
        if(this.currentUser == null){
            //初始化currentUser屬性:值從哪來呢?
            this.currentUser = UserUtils.getUser();
            //為什麼要初始化呢?
            //之前的為什麼都沒有初始化呢?
            //如果沒有初始化,可能呼叫該getter方法取到的值就是空
            //先初始化無非就是讓該方法不返回空值
        }
        return this.currentUser;
    }
  

 //currentUser屬性的setter方法setCurrentUser():正常
 //該方法在何時呼叫?在哪裡呼叫?由誰呼叫?
    public void setCurrentUser(User currentUser){
        this.currentUser = currentUser;
    }  
  

    //page屬性的getter方法 getPage():1.多了兩個註解;2.與一般getter不同,不是直接返回,而是先初始化再返回!兩種返回的區別在哪裡?
    @JsonIgnore
    @XmlTransient
    //任何時候取page屬性值時,都不允許取空值
    //該方法在何時呼叫?在哪裡呼叫?由誰呼叫?
    public Page<T> getPage(){
        if(this.page == null){
            //初始化:值從哪裡來呢?
            this.page = new Page();
        }
        //然後再返回
        return this.page;
    }     

   
    //page屬性的setter方法setPage():有返回值!
    //為什麼page屬性的setter方法會有返回值呢?
    //莫非該方法呼叫後,還能用到返回值?
    public Page<T> setPage(Page<T> page){
        this.page = page;
        return page;
    }

    //sqlMap屬性的getter方法getSqlMap():1.多了兩個註解;2.先初始化,再返回!   
    @JsonIgnore
    @XmlTransient
    //不允許sqlMap取空值
    public Map<String,string> getSqlMap(){
        if(this.sqlMap == null){
            //先初始化
            this.sqlMap = Maps.newHashMap();
        }
        return this.sqlMap;
    }
   
    //setInSqlMap屬性的setter方法:setSqlMap()正常
    public void setSqlMap(Map<String,String> sqlMap){
        this.sqlMap = sqlMap;   
    }
   

    //定義getInSqlMap()方法 getInSqlMap():1.該方法多了兩個註解;其他都正常!
    @JsonIgnore
    @XmlTransient
    //該方法允許獲取空值?還是一般情況下,inSqlMap不為空值?
    public Map<String,List<Object>> getInSqlMap(){
        return this.inSqlMap;
    }

    //定義setInSqlMap()方法setInSqlMap():十分不正常
    public void setInSqlMap(Map<String,List<Object>> inSqlMap){
        if(inSqlMap == null){
            return;//結束本方法的執行,前提:inSqlMap為null
        }
        //只有inSqlMap不為空值才進行設定操作
        //忽略
        StringBuffer sqlIn = new StringBuffer();
        //忽略
        StringBuffer sqlInKeySet = inSqlMap.keySet();
       
        for(String key : sqlInKeySet){

            List<Obeject> values = (List)inSqlMap.get(key);
           
            if(values.size() >= 1){
                for(int i = 0; i < values.size(); i++){
                    if(i == values.size() - 1){

                       sqlIn.append("'" + values.get(i) + "'");

                    }else{

                       sqlIn.append("'" + values.get(i) + "',");

                    }
                }
                sqlIn.insert(0,"AND" + key + "IN(");

                sqlIn.append(")");
            }
            getSqlMap().put("IN",sqlIn.toString());
        }
        this.inSqlMap = inSqlMap;
    }

    //先把方法都挨個定義出來,再逐一完善
   
    //再定義一個setInSqlMap方法(與上面引數不同) 
  
    //定義preInsert()方法:先忽略這個方法
    public abstract void preInsert();

    //定義preUpdate()方法:先忽略這個方法
    public abstract void preUpdate();


    //定義getIsNewRecord()方法
    @JsonIgnore
    public boolean getIsNewRecord(){
   
    }


    //定義setIsNewRecord()方法
    public void setIsNewRecord(){

    }


    //定義Global屬性的getter方法:先忽略這個方法
    @JsonIgnore
    public Global getGlobal(){

    } 

    //定義Dbname屬性的getter方法:先忽略這個方法
    public String getDbname(){

    }

    //定義equals方法:先忽略這個方法
    public boolean equals(){


    }
  
   
    //定義toString方法:先忽略這個方法
    public String toString(){
        return ReflectionToStringBuilder.toString(this);
    }

}

總結:首先這個類定義的屬性有:id;currentUser;page;sqlMap;inSqlMap;isNewRecord;DEL_FLAG_NORMAL;DEL_FLAG_DELETE;DEL_FLAG_AUDIT
//這個BaseEntity中定義的在結構上與其他實體類共同的方法有:實體類的構造方法,屬性的getter和setter方法
//在屬性的getter方法中,如何才能讓gett方法不取空值?在方法中先初始化該屬性!注意:在這裡初始化有前提條件:該屬性為空值null
//也就是說,邏輯是這樣:如果該屬性為null,那麼就先初始化該屬性!
//除此之外還定義的方法有:
     1.getGlobal()
     2.getDbname()
     3.equals()
     4.toString()
     5.preInsert()
     6.preUpdate()
//這裡5和6兩種方法是抽象方法

現在重點研究一下Map類
Map類是一個介面類:
其中,K和V表示兩種資料型別!
介面類中只能定義方法:定義屬性也沒用的,又不能被例項化
Map類定義的方法有:
size();isEmpty();containsKey(Object key);containsValue(Object value);這些都叫查詢操作!
get(Object key);put(K key, V value);remove(Object key);這些都叫更改操作
putAll(Map<? extends K, ? extends V> m);clear();這些叫批量操作
keySet();values();entrySet();
equals(Object o);hashCode();比較和hash操作!!


public interface Map<K,V> {
    // Query Operations(查詢操作)
    //int size()方法的說明
    /**
     * Returns the number of key-value mappings in this map.  If the
       (返回當前對映map例項中,鍵值對映對的數量;如果當前對映例項map中包含的元素的數量)
     * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
       (超過了Integer.MAX_VALUE,那麼呼叫該方法將只會返回Integer.MAX_VALUE)
     * <tt>Integer.MAX_VALUE</tt>.
     *
     * @return the number of key-value mappings in this map
     */(對返回值的說明:返回當前對映例項map中鍵值對對映的數量)
    int size();

    /**isEmpty()方法的說明
     * Returns <tt>true</tt> if this map contains no key-value mappings.
     * (如果該對映例項map中包含的鍵值對對映的數目為0,那麼將會返回true)
     * @return <tt>true</tt> if this map contains no key-value mappings
     */(對返回值的說明:如果該對映例項map中包含的鍵值對對映的數目為0,那麼將會返回true)
    boolean isEmpty();

    /**containsKey(Object key)方法的說明
     * Returns <tt>true</tt> if this map contains a mapping for the specified
       (如果當前對映例項map中一個有這個指定的key的對映對的話,就返回true)
     * key.  More formally, returns <tt>true</tt> if and only if
       (更正式的表達是:當且僅當這個對映例項map含有一個對該key的對映時,)
     * this map contains a mapping for a key <tt>k</tt> such that
       (比如:如果key為null,那就檢測map例項中的k有沒有為null的)
     * <tt>(key==null ? k==null : key.equals(k))</tt>.  (There can be
       (如果有,就返回true,如果key不為null,就將key和k做相等比較)
     * at most one such mapping.)
     *
     * @param key key whose presence in this map is to be tested
     * @return <tt>true</tt> if this map contains a mapping for the specified
     *         key
     * @throws ClassCastException if the key is of an inappropriate type for
     *         this map
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified key is null and this map
     *         does not permit null keys
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     */
    boolean containsKey(Object key);

    /**containsValue(Object value)方法說明
     * Returns <tt>true</tt> if this map maps one or more keys to the
       (如果當前對映例項中對於給定的這個value能對映一個或多個鍵的話,就返回true)
     * specified value.  More formally, returns <tt>true</tt> if and only if
       (理論上講,當且僅當map例項包含至少一個對給定值value的對映對時,才返回true)
     * this map contains at least one mapping to a value <tt>v</tt> such that
       (比如,先檢測value是否為null值,如果為null值就檢測v有沒有null值,如果有就返回true)
     * <tt>(value==null ? v==null : value.equals(v))</tt>.  This operation
       (如果沒有就返回false;如果不為null值,就將value與map中的v比較,有相等就返回true,否則返回false)
     * will probably require time linear in the map size for most
     * implementations of the <tt>Map</tt> interface.
     *
     * @param value value whose presence in this map is to be tested
     * @return <tt>true</tt> if this map maps one or more keys to the
     *         specified value
     * @throws ClassCastException if the value is of an inappropriate type for
     *         this map
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified value is null and this
     *         map does not permit null values
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     */
    boolean containsValue(Object value);

    /**get(Object key)方法說明
     * Returns the value to which the specified key is mapped,
      (返回指定key對映的那個值)
     * or {@code null} if this map contains no mapping for the key.
     *(如果這個map例項不含有對該key的對映就返回Null值)
     * <p>More formally, if this map contains a mapping from a key
      (如果這個map對映例項包含一個從該key到value的對映)
     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
      (比如先檢測有沒有對應的key值,如果有的話,就返回對應key的k對應的v)
     * key.equals(k))}, then this method returns {@code v}; otherwise
     * it returns {@code null}.  (There can be at most one such mapping.)
     *
     * <p>If this map permits null values, then a return value of
     * {@code null} does not <i>necessarily</i> indicate that the map
     * contains no mapping for the key; it's also possible that the map
     * explicitly maps the key to {@code null}.  The {@link #containsKey
     * containsKey} operation may be used to distinguish these two cases.
     *
     * @param key the key whose associated value is to be returned
     * @return the value to which the specified key is mapped, or
     *         {@code null} if this map contains no mapping for the key
     * @throws ClassCastException if the key is of an inappropriate type for
     *         this map
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified key is null and this map
     *         does not permit null keys
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     */
    V get(Object key);

    // Modification Operations

    /**
     * Associates the specified value with the specified key in this map
       (在該map例項中,將特定的值和特定的key聯絡起來)
     * (optional operation).  If the map previously contained a mapping for
       (如果 對映例項map中先前包含對該鍵的對映)
     * the key, the old value is replaced by the specified value.  (A map
        那麼, 舊值將會被指定的這個value值替換掉(我怎麼就沒想到過這個問題呢?)
     * <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only
     * if {@link #containsKey(Object) m.containsKey(k)} would return
     * <tt>true</tt>.)
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     *         (A <tt>null</tt> return can also indicate that the map
     *         previously associated <tt>null</tt> with <tt>key</tt>,
     *         if the implementation supports <tt>null</tt> values.)
     * @throws UnsupportedOperationException if the <tt>put</tt> operation
     *         is not supported by this map
     * @throws ClassCastException if the class of the specified key or value
     *         prevents it from being stored in this map
     * @throws NullPointerException if the specified key or value is null
     *         and this map does not permit null keys or values
     * @throws IllegalArgumentException if some property of the specified key
     *         or value prevents it from being stored in this map
     */
    V put(K key, V value);

    /**
     * Removes the mapping for a key from this map if it is present
       (從當前對映例項map中移除對該鍵的對映)
     * (optional operation).   More formally, if this map contains a mapping
     * from key <tt>k</tt> to value <tt>v</tt> such that
     * <code>(key==null ?  k==null : key.equals(k))</code>, that mapping
     * is removed.  (The map can contain at most one such mapping.)
     *
     * <p>Returns the value to which this map previously associated the key,
     * or <tt>null</tt> if the map contained no mapping for the key.
     *
     * <p>If this map permits null values, then a return value of
     * <tt>null</tt> does not <i>necessarily</i> indicate that the map
     * contained no mapping for the key; it's also possible that the map
     * explicitly mapped the key to <tt>null</tt>.
     *
     * <p>The map will not contain a mapping for the specified key once the
          (一旦方法呼叫返回,這個map例項將不再包含對這個特定key的對映)
     * call returns.
     *
     * @param key key whose mapping is to be removed from the map
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     * @throws UnsupportedOperationException if the <tt>remove</tt> operation
     *         is not supported by this map
     * @throws ClassCastException if the key is of an inappropriate type for
     *         this map
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified key is null and this
     *         map does not permit null keys
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     */
    V remove(Object key);


    // Bulk Operations

    /**
     * Copies all of the mappings from the specified map to this map
       (複製從指定map中複製所有的對映對到當前的map)
     * (optional operation).  The effect of this call is equivalent to that
       該方法呼叫的效果等同於
     * of calling {@link #put(Object,Object) put(k, v)} on this map once
       (依次挨個針對指定map中的每個鍵值對基於當前map呼叫put(k,v)方法)
     * for each mapping from key <tt>k</tt> to value <tt>v</tt> in the
     * specified map.  The behavior of this operation is undefined if the
     * specified map is modified while the operation is in progress.
     *
     * @param m mappings to be stored in this map
       (引數說明:要儲存到當前map中的所有鍵值對)
     * @throws UnsupportedOperationException if the <tt>putAll</tt> operation
     *         is not supported by this map
     * @throws ClassCastException if the class of a key or value in the
     *         specified map prevents it from being stored in this map
     * @throws NullPointerException if the specified map is null, or if
     *         this map does not permit null keys or values, and the
     *         specified map contains null keys or values
     * @throws IllegalArgumentException if some property of a key or value in
     *         the specified map prevents it from being stored in this map
     */
    void putAll(Map<? extends K, ? extends V> m);

    /**
     * Removes all of the mappings from this map (optional operation).
       (從當前map中移除所有的的對映對)
     * The map will be empty after this call returns.
     * 呼叫返回後,該對映將變成空對映
     * @throws UnsupportedOperationException if the <tt>clear</tt> operation
     *         is not supported by this map
     */
    void clear();


    // Views(記錄概覽集組操作)

    /**keySet()
     * Returns a {@link Set} view of the keys contained in this map.
       (返回對包含在該對映Map中的所有鍵的一個概覽)
     * The set is backed by the map, so changes to the map are
       (這個概覽組是受當前map對映支援的,所以對當前對映的變化都會反映到)
     * reflected in the set, and vice-versa.  If the map is modified
       (這個鍵的set中,反之亦然.)
     * while an iteration over the set is in progress (except through
     * the iterator's own <tt>remove</tt> operation), the results of
     * the iteration are undefined.  The set supports element removal,
     * which removes the corresponding mapping from the map, via the
     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
     * operations.
     *
     * @return a set view of the keys contained in this map
     */
    Set<K> keySet();

    /**values();
     * Returns a {@link Collection} view of the values contained in this map.
       (返回當前對映map中所有值的一個概覽組集)
     * The collection is backed by the map, so changes to the map are
     * reflected in the collection, and vice-versa.  If the map is
     * modified while an iteration over the collection is in progress
     * (except through the iterator's own <tt>remove</tt> operation),
     * the results of the iteration are undefined.  The collection
     * supports element removal, which removes the corresponding
     * mapping from the map, via the <tt>Iterator.remove</tt>,
     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
     * support the <tt>add</tt> or <tt>addAll</tt> operations.
     *
     * @return a collection view of the values contained in this map
     */
    Collection<V> values();

    /**entrySet();(記錄集方法)
     * Returns a {@link Set} view of the mappings contained in this map.
       (返回當前對映map中所有對映對的概覽集合)
     * The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa.  If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own <tt>remove</tt> operation, or through the
     * <tt>setValue</tt> operation on a map entry returned by the
     * iterator) the results of the iteration are undefined.  The set
     * supports element removal, which removes the corresponding
     * mapping from the map, via the <tt>Iterator.remove</tt>,
     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
     * <tt>clear</tt> operations.  It does not support the
     * <tt>add</tt> or <tt>addAll</tt> operations.
     *
     * @return a set view of the mappings contained in this map
     */
    Set<Map.Entry<K, V>> entrySet();

    /**
     * A map entry (key-value pair).  The <tt>Map.entrySet</tt> method returns
     * a collection-view of the map, whose elements are of this class.  The
     * <i>only</i> way to obtain a reference to a map entry is from the
     * iterator of this collection-view.  These <tt>Map.Entry</tt> objects are
     * valid <i>only</i> for the duration of the iteration; more formally,
     * the behavior of a map entry is undefined if the backing map has been
     * modified after the entry was returned by the iterator, except through
     * the <tt>setValue</tt> operation on the map entry.
     *
     * @see Map#entrySet()
     * @since 1.2
     */
     //這裡又定義一個介面:介面中又定義了很多方法,這裡先忽略!
    interface Entry<K,V> {
        /**
         * Returns the key corresponding to this entry.
         *
         * @return the key corresponding to this entry
         * @throws IllegalStateException implementations may, but are not
         *         required to, throw this exception if the entry has been
         *         removed from the backing map.
         */
        K getKey();

        /**
         * Returns the value corresponding to this entry.  If the mapping
         * has been removed from the backing map (by the iterator's
         * <tt>remove</tt> operation), the results of this call are undefined.
         *
         * @return the value corresponding to this entry
         * @throws IllegalStateException implementations may, but are not
         *         required to, throw this exception if the entry has been
         *         removed from the backing map.
         */
        V getValue();

        /**
         * Replaces the value corresponding to this entry with the specified
         * value (optional operation).  (Writes through to the map.)  The
         * behavior of this call is undefined if the mapping has already been
         * removed from the map (by the iterator's <tt>remove</tt> operation).
         *
         * @param value new value to be stored in this entry
         * @return old value corresponding to the entry
         * @throws UnsupportedOperationException if the <tt>put</tt> operation
         *         is not supported by the backing map
         * @throws ClassCastException if the class of the specified value
         *         prevents it from being stored in the backing map
         * @throws NullPointerException if the backing map does not permit
         *         null values, and the specified value is null
         * @throws IllegalArgumentException if some property of this value
         *         prevents it from being stored in the backing map
         * @throws IllegalStateException implementations may, but are not
         *         required to, throw this exception if the entry has been
         *         removed from the backing map.
         */
        V setValue(V value);

        /**
         * Compares the specified object with this entry for equality.
         * Returns <tt>true</tt> if the given object is also a map entry and
         * the two entries represent the same mapping.  More formally, two
         * entries <tt>e1</tt> and <tt>e2</tt> represent the same mapping
         * if<pre>
         *     (e1.getKey()==null ?
         *      e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &amp;&amp;
         *     (e1.getValue()==null ?
         *      e2.getValue()==null : e1.getValue().equals(e2.getValue()))
         * </pre>
         * This ensures that the <tt>equals</tt> method works properly across
         * different implementations of the <tt>Map.Entry</tt> interface.
         *
         * @param o object to be compared for equality with this map entry
         * @return <tt>true</tt> if the specified object is equal to this map
         *         entry
         */
        boolean equals(Object o);

        /**
         * Returns the hash code value for this map entry.  The hash code
         * of a map entry <tt>e</tt> is defined to be: <pre>
         *     (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
         *     (e.getValue()==null ? 0 : e.getValue().hashCode())
         * </pre>
         * This ensures that <tt>e1.equals(e2)</tt> implies that
         * <tt>e1.hashCode()==e2.hashCode()</tt> for any two Entries
         * <tt>e1</tt> and <tt>e2</tt>, as required by the general
         * contract of <tt>Object.hashCode</tt>.
         *
         * @return the hash code value for this map entry
         * @see Object#hashCode()
         * @see Object#equals(Object)
         * @see #equals(Object)
         */
        int hashCode();
    }

    // Comparison and hashing

    /**
     * Compares the specified object with this map for equality.  Returns
     * <tt>true</tt> if the given object is also a map and the two maps
     * represent the same mappings.  More formally, two maps <tt>m1</tt> and
     * <tt>m2</tt> represent the same mappings if
     * <tt>m1.entrySet().equals(m2.entrySet())</tt>.  This ensures that the
     * <tt>equals</tt> method works properly across different implementations
     * of the <tt>Map</tt> interface.
     *
     * @param o object to be compared for equality with this map
     * @return <tt>true</tt> if the specified object is equal to this map
     */
    boolean equals(Object o);

    /**
     * Returns the hash code value for this map.  The hash code of a map is
       (返回當前map的雜湊碼,當前map的雜湊碼定義為當前map中的所有對映記錄中每條對映記錄的hash碼值)
     * defined to be the sum of the hash codes of each entry in the map's
     * <tt>entrySet()</tt> view.  This ensures that <tt>m1.equals(m2)</tt>
     * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps
     * <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of
     * {@link Object#hashCode}.
     *
     * @return the hash code value for this map
     * @see Map.Entry#hashCode()
     * @see Object#equals(Object)
     * @see #equals(Object)
     */
    int hashCode();

}

看第二部分的實體類:DataEntity實體類

//定義一個抽象類
//抽象是具體的反義
//也就是說抽象不能具體化=不能例項化
//這樣的類只能用來繼承了
//抽象類中是含有構造方法的!
//注意這裡為什麼要加上<T>呢?
public abstract class DataEntity<T> extends BaseEntity<T>{
    //private 表示私有,歸誰私有呢?就是歸類DataEntity私有
    //一旦規定為私有,該變數只能在本類中使用了!
    private static final long serialVersionUID = 1L;
    //protected 表示私有財產保護 私有財產保護什麼意思呢?
    //變數歸類所有,但類的子類都能使用
    //抽象類中定義的變數一定包含大量的protected型別的變數!

    protected String remarks;//表示注意類似於note(備註)
   
    protected User createBy;//表示建立者

    protected Date createDate;//表示建立日期
 
    protected User updateBy;//表示更新者

    protected String delFlag;//表示刪除標誌:0表示正常,1表示刪除

    protected String aab301;//表示區域

    protected String aaf013;//應該也表示區域

    protected String aaf030;//應該也表示區域
   
    //類的無參構造方法:DataEntity()
    //該方法呼叫後,會做什麼事情呢?
    public DataEntity(){
        //呼叫該方法後會初始化delFlag屬性為0
        //該方法在何時呼叫?
        //子類呼叫無參構造方法時,呼叫該方法
        this.delFlag = "0";
    }
  
    //該類的有參構造方法:DataEntity(String id)
    public DataEntity(String id){
        //該方法呼叫後,會呼叫父類中的有參構造方法!
        //那這個方法呼叫後,會做什麼事情呢?還是初始化麼?
        //該方法在何時呼叫?
        //子類的有參構造方法呼叫時,呼叫該方法!
        super(id);
    }
 
    //問一個問題:這連個構造方法在何時呼叫?由誰呼叫呢?

    //這裡定義一個方法getUserArea(T entity)
    //這個方法做什麼呢?
    //什麼時候呼叫這個方法?何時呼叫這個方法呢?在哪裡呼叫這個方法?
    public T getUserArea(T entity){

       //這裡出現了一種if結構:這種結構用來處理的邏輯通常是什麼?
       //先別管這個,把所有的if程式碼全忽略
       //只在意最關鍵的事情:無非就是:初始化類的三個表示區域的屬性:aaf030,aaf013,aab301
       //為什麼要在這裡初始化呢?
       //初始化不是有自己的setter麼?
       //何時/在哪裡才會用到這個方法呢?
       if(!UserUtils.getUser().isAdmin()){
   
           UserArea userArea = UserUtils.getUserArea();

           if(StringUtils.isNotBlank(userArea.getAaf030())){
               this.aaf030 = userArea.getAaf030();
           }
          
           if(StringUtils.isNotBlank(userArea.getAaf013())){
               this.aaf013 = userArea.getAaf013();
           }
 
           if((StringUtils.isNotBlank(userArea.getAab301()))&&(!"340220".equals(userArea.getAab301()))){
               this.aab301 = userArea.getAab301();
           }            
       }
       return entity;
    
    }
    //這裡的getUserArea()方法,

    //這裡再定義一個方法preInsert()
    //該方法在何時呼叫?由誰呼叫?在哪裡呼叫?
    //何時呼叫?在執行插入方法之前!
    //由誰呼叫?實體的例項!
    public void preInsert(){
        //這裡先忽略if(非關鍵程式碼)
        //很明顯這句程式碼是初始化id
        if(!this.isNewRecord){
            setId(IdGen.uuid());
        }
        //這句程式碼也忽略掉(非重要程式碼!)
        User user = UserUtils.getUser();
        //忽略if程式碼:初始化updateBy和createBy
        if(StringUitls.isNotBlank(user.getId())){
            this.updateBy = user;
            this.createBy = user;
        }
        this.updateDate = new Date();
        this.createDate = this.updateDate;
    }
    //這個方法在很大程度上會覺得暫時還不需要呢,那就先完全徹底的忽略它!!

    //這裡定義一個preUpdate()方法
    public void preUpdate(){
        //先忽略這種程式碼!!
        User user = UserUtils.getUser();
        //也忽略這種程式碼!!
        //很明顯就是初始化update屬性
        if(StringUtils.isNotBlank(user.getId())){
            this.update = user;
        }
        //這程式碼就是初始化updateDate屬性
        this.updateDate = new Date();
    }
    //這個方法在何時呼叫?由誰呼叫?在哪裡呼叫?
    //似乎在這裡完全體現不出來,那就徹底忽略這個方法!!

    .......getter and setter.......

   // 剩下的所有方法就是對上述屬性的get和set方法,就不贅述了!

}
總結:
     1.該類和其他類的在結構上的共同點是:屬性 + 構造方法 + getter和setter
     2.該類和其他類的在結果上的不同點是:多了三個方法: getUserArea(),preInsert(),preUpdate()
     3.getUserArea()方法不同於其他兩種方法的地方是:用到了T
     4.該類定義了七個屬性:remarks,createBy,createDate,updateBy,updateDate,aab301,aaf013,aaf030

//任何一個類,都要非常清楚它的屬性,這很重要,直接決定你清不清晰這個類

再來看第三部分的實體:PersonalApplyBean如下
public class PersonalApplyBean extends DataEntity<PersonalApplyBean>{
    private static final long serialVersionUID = 1L;
 
    private String certType;
    private String idcard;
    private String name;
    private String sex;
    private String nation;
    private String regionalCode;
    private String cardPhoto;
    private String frontPhoto;
    private String backPhoto;
    private String verificatePhoto;
    private String certValidity;
    private String nationality;
    private String bankNo;
    private String bankNum;
    private String ryzt;
    private String aac001;
    private String phone;
    private String address;
    private String aab001;
    private String aab004;
    private String opinions;
    private String rylb;
    private String status;
    private String brithday;
    private String checkDate;

    private String message;

    private String agentidcard;
 
    private String agentname;

    public PersonApplyBean(){
        super();
    }

    public PersonalApplyBean(String id){
        super(id);
    }
    .........剩下的為屬性的getter和setter.........         
}
//以上三個實體類的關係:
  PersonalApplyBean繼承DataEntity<T>
  DataEntity<T>繼承BaseEntity<T>
//不同的是:DataEntity<T>和BaseEntity<T>都是抽象類
//讓程式現在人腦中跑一圈,這件事情很有意義!
//PersonalApplyBean是肯定要例項化的
//但是另外兩個抽象類是不能例項化的
//假如Bean例項化呼叫的是無參構造方法
//該無參方法會幹兩件事情:
  1.建立本類的一個例項
  2.呼叫父類中的無參構造方法
  父類中的無參構造方法執行後,只做一件事情:將父類的del_flag屬性初始化為0
  然後呢?

第二天:再讀這實體層!!!如下:

/操作層Bean:PersonalApplyBean(表示個人申請)

public class PersonalApplyBean extends DataEntity<PersonalApplyBean>{
    private static final long serialVersionUID = 1L;

    private String certType;//證件型別
    private String idcard;//身份證號
    private String name;//姓名
    private String sex;//性別
    private String nation;//民族
    private String regionalCode;//區域
    private String cardPhoto;//證件照
    private String frontPhoto;//正面照
    private String backPhoto;//背面照
    private String verificatePhoto;//驗證照
    private String certValidity;//證件有效期
    private String nationality;//國籍
    private String bankNo;//合作銀行
    private String bankNum;//合作網點
    private String ryzt;//人員狀態
    private String acc001;//參保號
    private String phone;//手機號碼
    private String address;//居住地址
    private String aab001;//單位編碼
    private String aab004;//單位名稱
    private String opinions;//稽核意見
    private String rylb;//人員類別
    private String status;//狀態
    private String birthday;//出生日期
    private Date checkDate;//稽核日期
    
    private String message;

    private String agentidcard;//代理人證件型別
    private String agentname;//代理人證件號碼
   
    .....有參和無參構造方法....
    public PersonalApplyBean(){
        super();
    }

    public PersonalApplyBean(String certType){
        super(id);
    }
   
    ......屬性的getter和setter.....
    
}

//第一底層的Bean:DataEntity<T>
public abstract class DataEntity<T> extends BaseEntity<T>{
    private static final long serialVersionUID = 1L;

    protected String remarks;//備註
    protected String createBy;//建立者
    protected String createDate;//建立日期
    protected String updateBy;//更新者
    protected String updateDate;//更新日期
    protected String delFlag;//刪除標誌
    protected String aab301;//區域
    protected String aaf013;//區域
    protected String aaf030;//區域

    .....無參和有參的構造方法....
    public DataEntity(){
        this.delFlag = "0";
    }

    public DataEntity(String id){
        super(id);
    }


    ....所有屬性的getter和setter.....
    
   //到現在為止都不需要<T>
   //下面就用到了
   ....定義getUserArea(T entity)方法.....
   public T getUserArea(T entity){

   }

   ....定義preInsert()方法....
   public void preInsert(){

   }
   
   
   ...定義preUpdate()方法....
   public void preUpdate(){

   }

       
}

第二底層的實體類:BaseEntity

public abstract class BaseEntity<T> implements Serializable{
    private static final long serialVersionUID = 1L;
  
    protected String id;
    protected User currentUser;
    protected Page<T> page;
    protected Map<String,String> sqlMap;
    protected Map<String,List<Object>> inSqlMap;
    protected boolean isNewRecord = false;
    
    public static final String DEL_FLAG_NORMAL = "0";
    public static final String DEL_FLAG_DELETE = "1";
    public static final String DEL_FLAG_AUDIT = "2";

    ....定義無參和有參構造方法.....
    public BaseEntity(){

    }    

    public BaseEntity(String id){
        this();
        this.id = id;
    }

    .....屬性的getter和setter....

    ...定義方法簽名:preInsert()
    public abstract void preInsert();

    
    ...定義方法簽名:preUpdate()
    public abstract void preUpdate();

   
    ...定義getGlobal()方法...
    public Global getGlobal(){

    }

    ...定義getDbName()方法...
    public String getDbname(){

    }

    ...定義equals()方法...
    public boolean equals(Object obj){

    }
    

    ...定義toString()方法....
    public String toString(){

    }

}


總結:
    注意:如果將所有的實體都整合在一起的話
    會發現,實體中的屬性是多於表的欄位的,方法也不僅僅限於對屬性的get和set
    這些屬性分為:表屬性,和其他屬性
    這些方法分為:表屬性方法,其他屬性方法和其他方法
    在清楚了表屬性和對應的屬性方法之後,密切注意其他屬性和其他方法;
    所有的實體都由屬性和方法組成
    方法一般都是對屬性的get和set
    先關注屬性:
    1.三個實體的分解實際上是把一張表的所有欄位以及需要的其他屬性各分擔到不同的實體上;
    2.越往底層,相應的實體所具備的屬性就越穩定,適用範圍就越廣;
    再關注方法:
    1.越往底層,定義的方法本身就越穩定!
    
    
注意:
   第二層和第三層也可以合併為一層,但合併為一層之後,這一層的程式碼量將變成原來的兩倍
   閱讀起來心煩,修改起來心塞;能分開的最好分開!事實上,這三成都可以合併為一層的,但是你能想象出合併出來的樣子麼?
   你還能在合併出來的大層中進行行雲流水,穩而不亂的操作麼?
   肯定要拆成這三塊?
   問題是:怎麼拆了之後,還能很好的合在一起,並且像合在一起的那樣去工作呢?
   這才是應該關注的問題:
   我們一般這麼操作:
   1.將比較穩定的部分拆成一個抽象類,剩下的不穩定的部分拆成一個實體層,然後讓這個實體層繼承這個抽象類
   2.接著,在這些比較穩定的部分中把更穩定的部分再拆成一個抽象類,然後,讓上個抽象類再繼承當前這個抽象類

   這就形成了你現在看到的這個樣子!!!

   在任何重複的過程中,第一次永遠是最難受的,第二次會舒服很多!
   因為:重複的力量在前期雖然做不到累乘很少但那本身也是一個累加啊
   現在:先關注那些其他方法去!
   在DataEntity<T>中,首先多出來的就是getUserArea(T entity)方法
   對這個方法:至少搞明白的問題有做什麼?由誰呼叫?在哪裡呼叫?在何時呼叫?
   至於方法的返回值和引數暫時先不考慮!!!!(因為這是個後續問題,不是主要矛盾)
   回答第一個問題:首先可以通過方法名來理解:獲取使用者區域=換句話說,呼叫這個方法之後,可以獲取到使用者的區域!!!
   思考如下問題:最終是誰獲取了使用者的區域呢? 如何能獲取到使用者的區域呢? 為什麼要獲取使用者的區域呢?

   在回答這些問題之前:
   先了解兩個類:UserArea 和 UserUtils
   先了解一下類UserUtils:
   
   public class UserUtils{
       private static UserDao userDao = (UserDao)SpringContextHolder.getBean(UserDao.class);
       private static RoleDao roleDao = (RoleDao)SpringContextHolder.getBean(RoleDao.class);
       private static MenuDao menuDao = (MenuDao)SpringContextHolder.getBean(MenuDao.class);
       private static AreaDao areaDao = (AreaDao)SpringContextHolder.getBean(AreaDao.class);
       private static UserAreaDao userAreaDao = (UserAreaDao)SpringContextHolder.getBean(UserAreaDao.class);
       private static Af08Dao af08Dao = (Af08Dao)SpringContextHolder.getBean(Af08Dao.class);
       private static Af02Dao af02Dao = (Af02Dao)SpringContextHolder.getBean(Af02Dao.class);
       private static OfficeDao officeDao = (OfficeDao)SpringContextHolder.getBean(OfficeDao.class);


       public static final String USER_CACHE = "userCache";
     
       public static final String USER_CACHE_ID_ = "id_";

       public static final String USER_CACHE_LOGIN_NAME_ = "ln";
  
       public static final String USER_CACHE_LIST_BY_OFFICE_ID ="oid_";

       public static final String USER_AREA_CACHE ="userAreaCache";

       public static final String USER_AREA_CACHE_ID_ = "uaId";

       public static final String AREA_CACHE = "areaCache";

       public static final String AREA_CHACHE_ID = "aId";
   
       public static final String CACHE_ROLE_LIST = "roleList";

       public static final String CACHE_MENU_LIST = "menuList";

       public static final String CACHE_AF08_ALL_LIST = "af08AllList";
     
       public static final String CACHE_AF02_ALL_LIST = "af02AllList";

       public static final String CACHE_OFFICE_LIST = "officeList";
   
       public static final String CACHE_OFFICE_ALL_LIST ="officeAllList";
 
       ......定義無參構造方法....
       public UserUtils(){}
       ....定義get方法......
       //準備獲取什麼?
       public static User get(String id){


       }       
   
       ....定義getByLoginName(String loginName)方法....
       //通過登入名稱獲取什麼呢?
       public static User getByLoginName(String loginName){

       }

       ....定義無參clearCache()方法...
       public static void clearCache(){

       }

       ...定義有參clearCache(User user)方法...
       public static void clearCache(User user){

       }

   
       ...定義getUser()方法...
       public static User getUser(){

       }

       ...定義getRoleList()方法......
       public static List<Role> getRoleList(){
           
       }

       ...定義getMenuList()方法....
       public static List<Menu> getMenuList(){

       }

    
       ...定義getUserMenuList(String roleId)方法....
       public static List<Menu> getUserMenuList(String roleId){

       }


       ...定義getUserArea()方法...
       public static UserArea getUserArea(){

       }

       ...定義無參getAreaList()方法....
       public static List<Area> getAreaList(){

       }

       ...定義getAreaList(String parentId)方法......
       public static List<Area> getAreaList(String parentId){

       }

       ...定義getAf08AllList()方法...
       public static List<Af08> getAf08AllList(){

       }

       ...定義getAf02AllList()....
       public static List<Af02> getAf02List(){

       }

       ...定義getOfficeList().....
       public static List<Office> getOfficeList(){

       }


       ...定義getOfficeAllList()方法....
       public static List<Office> getOfficeAllList(){

       }


       ...定義getSubject()方法....
       public static Subject getSubject(){

 
       }

       ...定義getPrincipal()方法....
       public static SystemAuthorizingRealm.Principal getPrincipal(){

       }
       
       ...定義getSession()方法...
       public static Session getSession(){

       }

       ...定義getCache(String key)方法....
       public static Object getCache(String key){

       }

       ...定義getCache(String key,Object defaultValue)....
       public static Object getCache(String key,Object defaultValue){

       }
       ...定義putCache()方法.....
       public static void putCache(String key,Object value){

       }
       ...定義removeCache()方法....
       public static void removeCache(){

       }

}

相關推薦

SSM入門:徹底體層entity/POJO

一.基礎實體類部分:BaseEntity<T> @SupTreeList 又定義一個抽象類BaseEntity,該抽象類實現介面Serializable public abstract class BaseEntity<T> implements S

div佈局快速入門徹底CSS盒子模式)

前言 如果你想嘗試一下不用表格來排版網頁,而是用CSS來排版你的網頁,也就是常聽的用DIV來編排你的網頁結構,又或者說你想學習網頁標準設計,再或者說你的上司要你改變傳統的表格排版方式,提高企業競爭力,那麼你一定要接觸到的一個知識點就是CSS的盒子模式,這就是DIV排版的

徹底px,em和rem的區別

無法 屏幕分辨率 中國 重新 分辨 應對 小時 font targe   國內的設計大師都喜歡用px,而國外的網站大都喜歡用em和rem,那麽三者有什麽區別,又各自有什麽優劣呢?   px特點:   1.IE無法調整那些使用px作為單位的字體大小;   2.國外大部分網站能

徹底 JavaScript 執行機制

函數 大名 定時 意思 技術 渲染 文字 根據 java 本文的目的就是要保證你徹底弄懂javascript的執行機制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老鳥,不論是面試求職,還是日常開發工作,我們經常會遇到這樣的情況:給定的幾行

[轉]js模塊化編程之徹底CommonJS和AMD/CMD!

歷史 js插件 服務 conf 原因 遇到 reg func depend 原文: https://www.cnblogs.com/chenguangliang/p/5856701.html -----------------------------------------

徹底字符串常量池等相關問題

加載 結果 包裝 == str2 ringbuf 總結 範圍 con 前言:   在平時我們使用字符串一般就是拿來直接搞起,很少有深入的去想過這方面的知識,導致別人在考我們的時候,會問 String str = new String("123"); 這個一行代碼執行創建了幾

徹底HTTP緩存機制及原理(轉載)

一次 chrom https 分開 res 技術 觸發 明顯 總結 https://www.cnblogs.com/chenqf/p/6386163.html 前言 Http 緩存機制作為 web 性能優化的重要手段,對於從事 Web 開發的同學們來說,應該是知識體系庫中的

徹底python編碼

def 不能 全世界 寬度 解決方法 增加 str cnblogs style 在編寫python程序的過程中,中英文混用經常會出現編碼問題。圍繞此問題,本文首先介紹編碼的含義及常用編碼,隨後列舉幾個python經常遇到的編碼異常及解決方法,接著列舉筆者在實踐中遇到的異

30分鐘徹底flex布局

display 分享 成了 一次 ane 計算 是不是 老師 developer 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 本文由elson發表於雲+社區專欄 目前在不考慮IE以及低端安卓機(4.3-)的兼容下,已經可以放心使用flex進行布局了。什麽

一個案例徹底如何正確使用 mysql inndb 聯合索引

audit drop sim itl -o 例子 一次 葉子 xpl 摘要: 有一個業務是查詢最新審核的5條數據 ``sql SELECTid,titleFROMth_contentWHEREaudit_time&lt; 1541984478 ANDstatus=

這一次,徹底 JavaScript 執行機制

本文的目的就是要保證你徹底弄懂javascript的執行機制,如果讀完本文還不懂,可以揍我。 文章轉自:https://juejin.im/post/59e85eebf265da430d571f89 不論你是javascript新手還是老鳥,不論是面試求職,還是日常開發

《從零構建前後分離的web專案》:前端終 - 徹底前端效能優化與上線 (多圖預警)

4000字長文,多圖預警!!!流量慎入!! 效能優化 - 屌絲前端效能優化、上線一條龍 大家好我又來了,本章給大家帶來的內容是:上線和上線後的效能優化 專案地址 實戰預覽地址 實戰專案地址 本章程式碼地址 本章你會了解 前端需要了解的 docker 基礎知識 部署前端專

徹底css中單位px和em,rem的區別

在CSS中,尺寸單位分為兩類:相對長度單位和絕對長度單位。相對長度單位按照不同的參考元素,又可以分為字型相對單位和視窗相對單位。字型相對單位有:em、ex、ch、rem;視窗相對單位有:vw、vh、vmin、vmax幾種。絕對長度單位則是固定尺寸,它們採用的是物理度量單位:cm、mm、in、px、pt以及pc

徹底JS原型與繼承

本文由淺到深,循序漸進的將原型與繼承的抽象概念形象化,且每個知識點都搭配相應的例子,儘可能的將其通俗化,而且本文最大的優點就是:長(為了更詳細嘛)。 一、原型 首先,我們先說說原型,但說到原型就得從函式說起,因為原型物件就是指函式所擁有的prototype屬性(所以下文有時說原型,有時說prototype

這次,徹底介面及抽象類

本文出自伯特的《LoulanPlan》,轉載務必註明作者及出處。 本文旨在討論抽象類和介面的作用、例項及使用場景,都是我的理解和總結。更多關於介面和抽象類的概念知識,可自行查閱相關文件。 1. 抽象類及其作用 抽象類,顧名思義,即類的抽象。 在介紹面向物件概念時,我們知道類是客觀事物的抽象,

徹底HTTP快取機制及原理

01、前言 Http 快取機制作為 web 效能優化的重要手段,對於從事 Web 開發的同學們來說,應該是知識體系庫中的一個基礎環節,同時對於有志成為前端架構師的同學來說是必備的知識技能。僅僅只是知道瀏覽器會對請求的靜態檔案進行快取是不夠的,為什麼被快取,快取是怎樣生效的、

30分鐘徹底flex佈局

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~ 本文由elson發表於雲+社群專欄 目前在不考慮IE以及低端安卓機(4.3-)的相容下,已經可以放心使用flex進行佈局了。什麼是flex佈局以及它的好處,這裡就不再贅述。 在這篇文章裡,想說說fl

徹底css中單位px和em,rem的區別

國內的設計師大都喜歡用px,而國外的網站大都喜歡用em和rem,那麼三者有什麼區別,又各自有什麼優劣呢?PX特點 IE無法調整那些使用px作為單位的字型大小; 國外的大部分網站能夠調整的原因在於其使用了em或rem作為字型單位; Firefox能夠調整px和em,r

徹底px,em和rem的區別 (贊)

國內的設計大師都喜歡用px,而國外的網站大都喜歡用em和rem,那麼三者有什麼區別,又各自有什麼優劣呢? px特點:   1.IE無法調整那些使用px作為單位的字型大小;   2.國外大部分網站能夠調整的原因在於其使用了em或rem作為字型單位;   3.Firef

知識普及:徹底css中單位px和em,rem的區別

        國內的設計師大都喜歡用px,而國外的網站大都喜歡用em和rem,那麼三者有什麼區別,又各自有什麼優劣呢? PX特點 1. IE無法調整那些使用px作為單位的字型大小; 2.