MP實戰系列(三)之實體類講解


首先說一句,mybatis plus實在太好用了!

mybaits plus的實體類:

以我博客的用戶類作為講解

package com.blog.entity;

import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableLogic;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;

import java.io.Serializable;
import java.util.Date;

/**
 * 
 * 
 * @author youcong
 * @email ${email}
 * @date 2018-04-21 15:27:01
 */
@TableName("user")
public class UserEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 用戶ID
     */
    @TableId(type=IdType.AUTO)
    private Integer user_id;
    /**
     * 用戶名
     */
    private String username;
    /**
     * 性別
     */
    private String sex;
    /**
     * 電話
     */
    private String phone;
    /**
     * 密碼
     */
    private String password;
    /**
     * 等級
     */
    private Integer level;
    /**
     * 用戶創建時間
     */
    @TableField(value="create_time")
    private String createTime;
    /**
     * 郵箱
     */
    private String email;
    /**
     * 登錄標識
     */
    private Integer logo;

    /**
     * 設置:用戶ID
     */
    public void setUserId(Integer user_id) {
        this.user_id = user_id;
    }
    /**
     * 獲取:用戶ID
     */
    public Integer getUserId() {
        return user_id;
    }
    /**
     * 設置:用戶名
     */
    public void setUsername(String username) {
        this.username = username;
    }
    /**
     * 獲取:用戶名
     */
    public String getUsername() {
        return username;
    }
    /**
     * 設置:性別
     */
    public void setSex(String sex) {
        this.sex = sex;
    }
    /**
     * 獲取:性別
     */
    public String getSex() {
        return sex;
    }
    /**
     * 設置:電話
     */
    public void setPhone(String phone) {
        this.phone = phone;
    }
    /**
     * 獲取:電話
     */
    public String getPhone() {
        return phone;
    }
    /**
     * 設置:密碼
     */
    public void setPassword(String password) {
        this.password = password;
    }
    /**
     * 獲取:密碼
     */
    public String getPassword() {
        return password;
    }
    /**
     * 設置:等級
     */
    public void setLevel(Integer level) {
        this.level = level;
    }
    /**
     * 獲取:等級
     */
    public Integer getLevel() {
        return level;
    }
    /**
     * 設置:用戶創建時間
     */
    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }
    /**
     * 獲取:用戶創建時間
     */
    public String getCreateTime() {
        return createTime;
    }
    /**
     * 設置:郵箱
     */
    public void setEmail(String email) {
        this.email = email;
    }
    /**
     * 獲取:郵箱
     */
    public String getEmail() {
        return email;
    }
    /**
     * 設置:登錄標識
     */
    public void setLogo(Integer logo) {
        this.logo = logo;
    }
    /**
     * 獲取:登錄標識
     */
    public Integer getLogo() {
        return logo;
    }
}

 

上述的注解什么意思,為什么用,我在第一篇MP實戰中提過也加以描述說過。不過,今天我還是要強調一下,@TableName該注解用英文翻譯就是"表名"的意思,通常在這里面寫實體對應的表名,方便映射。大家還記得hibernate嗎?hibernate中有個配置文件叫:hibernater-cfg.xml,該配置文件主要配置hibernate的數據源和實體映射掃描等等,這個實體映射掃描,就是通過注解,之前是每個實體對應的xml文件,而在這個xml文件中配置實體對應表的屬性。后來hibernate進行升級了,如果是每一個實體對應一個xml文件,隨着項目越來越大,xml文件管理起來也是個問題,於是注解,應需而生。

大家可以參考我的關於spring+hibernate+springmvc框架搭建的例子,看其中有一個實體就是通過注解的形式映射。這個與mybatis plus實體注解也是一個意思,並無多大差異。下面貼個代碼方便講解:

package com.ssh.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * Created by XRog
 * On 2/2/2017.2:03 PM
 */
@Data
@Entity
@Table(name = "Person")
public class Person {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "created")
    private Long created = System.currentTimeMillis();

    @Column(name = "username")
    private String username;

    @Column(name = "address")
    private String address;

    @Column(name = "phone")
    private String phone;

    @Column(name = "remark")
    private String remark;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getCreated() {
        return created;
    }

    public void setCreated(Long created) {
        this.created = created;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
    
    
}

這是hibernate的實體注解, @Data : 注解在類上, 為類提供讀寫屬性, 此外還提供了 equals()、hashCode()、toString() 方法

                                             @Entity 對實體注釋。任何Hibernate映射對象都要有這個注釋

              @Table 的意思與mybatis plus中的@TableName意思是一樣的

                                             @Id和@GeneratedValue是對主鍵的標識,這里與mybatis plus中的@TableId意思也是一樣的

                                             @Column 意思就如其名,標識列的,在屬性上打上該注解,使其與數據表中的字段名進行映射,而mybatis plus這里的@TableField雖有映射的意思,但是還有其他的意思,

                                     比如mybatis中,為什么要用resultType?為什么要用resultMap?原因很簡單,一句話即可解釋,當實體屬性與表的字段名一致時,自動映射,當不一致時,需手動映射。

                                           @TableFiled在此就有這個作用

@TableName的源碼如下:

/**
 * Copyright (c) 2011-2014, hubin (jobob@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.baomidou.mybatisplus.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * <p>
 * 數據庫表相關
 * </p>
 *
 * @author hubin
 * @since 2016-01-23
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TableName {

    /**
     * <p>
     * 實體對應的表名
     * </p>
     */
    String value() default "";

    /**
     * <p>
     * 實體映射結果集
     * </p>
     */
    String resultMap() default "";

}

這里對@Retention和@Target做簡單的說明:

元數據

也叫元注解,是放在被定義的一個注解類的前面 ,是對注解一種限制。

談下這兩個: @Retention 和 @Target  

@Retention :用來說明該注解類的生命周期。它有以下三個參數:

RetentionPolicy.SOURCE  : 注解只保留在源文件中

RetentionPolicy.CLASS  : 注解保留在class文件中,在加載到JVM虛擬機時丟棄

RetentionPolicy.RUNTIME  : 注解保留在程序運行期間,此時可以通過反射獲得定義在某個類上的所有注解。

@Target :  用來說明該注解可以被聲明在那些元素之前。

ElementType.TYPE:說明該注解只能被聲明在一個類前。

ElementType.FIELD:說明該注解只能被聲明在一個類的字段前。

ElementType.METHOD:說明該注解只能被聲明在一個類的方法前。

ElementType.PARAMETER:說明該注解只能被聲明在一個方法參數前。

ElementType.CONSTRUCTOR:說明該注解只能聲明在一個類的構造方法前。

ElementType.LOCAL_VARIABLE:說明該注解只能聲明在一個局部變量前。

ElementType.ANNOTATION_TYPE:說明該注解只能聲明在一個注解類型前。

ElementType.PACKAGE:說明該注解只能聲明在一個包名前。

 

@TableId源碼:

/**
 * Copyright (c) 2011-2014, hubin (jobob@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.baomidou.mybatisplus.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.baomidou.mybatisplus.enums.IdType;

/**
 * <p>
 * 表主鍵標識
 * </p>
 *
 * @author hubin
 * @since 2016-01-23
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TableId {

    /**
     * <p>
     * 字段值(駝峰命名方式,該值可無)
     * </p>
     */
    String value() default "";

    /**
     * <p>
     * 主鍵ID
     * </p>
     * {@link IdType}
     */
    IdType type() default IdType.NONE;

}

@TableId中有這么幾個屬性,其中用的比較多的就是屬Type

Type常用的枚舉有:

AUTO 主鍵自增

ID_WORKER

INPUT 主鍵以輸入的方式

NONE 默認一般是自增

UUID UUID方式

我個人用的比較多,一個是AUTO,另外一個是UUID,這兩個能滿足大多數的項目需求

 

@TableFied源碼:

/**
 * Copyright (c) 2011-2014, hubin (jobob@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.baomidou.mybatisplus.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.baomidou.mybatisplus.enums.FieldFill;
import com.baomidou.mybatisplus.enums.FieldStrategy;

/**
 * <p>
 * 表字段標識
 * </p>
 *
 * @author hubin sjy tantan
 * @since 2016-09-09
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TableField {

    /**
     * <p>
     * 字段值(駝峰命名方式,該值可無)
     * </p>
     */
    String value() default "";

    /**
     * <p>
     * 當該Field為類對象時, 可使用#{對象.屬性}來映射到數據表.
     * </p>
     * <p>
     * 支持:@TableField(el = "role, jdbcType=BIGINT)<br>
     * 支持:@TableField(el = "role, typeHandler=com.baomidou.xx.typehandler.PhoneTypeHandler")
     * </p>
     */
    String el() default "";

    /**
     * <p>
     * 是否為數據庫表字段
     * </p>
     * <p>
     * 默認 true 存在,false 不存在
     * </p>
     */
    boolean exist() default true;

    /**
     * <p>
     * 字段驗證策略
     * </p>
     * <p>
     * 默認 非 null 判斷
     * </p>
     */
    FieldStrategy strategy() default FieldStrategy.NOT_NULL;

    /**
     * <p>
     * 字段自動填充策略
     * </p>
     */
    FieldFill fill() default FieldFill.DEFAULT;
}

@TableField是比較常用的注解,有的時候覺得ajax要傳實體(這個實體包含其它實體類屬性),通常規范的做法是寫個dto,直接傳輸,一來復用方便,二來簡潔清楚,我們開發中通常不推薦一個實體中嵌入其他實體的屬性,但是有的時候,人有點懶,需求有點變態,為了加快速度,就直接在一個實體中,寫其他實體屬性。

這就好比,在一個html頁面中,建議寫外部js和css,一來規范,二來方便管理,三來復用,不過規范通常是讓人痛苦的,不過對於時常變更的項目需求而言是快樂的,因為代碼規范不亂,但是對於小公司而言,有的時候為了加快項目進度,不管三七二十一,行內樣子能解決,絕對不用外部,最后一個頁面內置一大堆css,js,而且html標簽中又嵌入一大堆css標簽或者js函數等,等到要優化時,有種想罵人的沖動。

題外話就不多說了,總而言之,規范開發雖然是痛苦,但是對於未來是很有益的,堅持規范,做一個代碼潔癖的人!目前我還是不符合。至少我還是與前者所說的,占了一半。深刻的體會到,代碼不規范,亂七八糟帶來的影響。@TableField中的exist屬性就是為了當你的實體包含其它實體時,可以指定它,默認為true,需要指定為false,true的意思是該字段在數據表中存在,false是不存在,通常的話,如果你的自動生成查,查所有,而不使用setSqlSelect()方法指定具體的字段時,如果你的實體中包含其它屬性,但又沒有使用exist時,會出現找不到列異常。避免該異常的方法就是指定exist為false,不過開發過程中,不管怎么樣建議使用setSqlSelect()方法,因為sql優化。調用該方法指明需要字段就是進行最簡單的sql優化。一個個簡單的sql優化,對於一個系統還是很有威力的。

當然使用@TableField的場景是當你的實體屬性與數據表不一致時,進行手動映射,如果一致,就會自動映射。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM