通用Mapper簡單使用介紹


通用Mapper使用介紹

  通用Mapper是簡化mybatis操作的一個框架,使用它就不需要再建立xml映射文件了,也不用在dao接口(注解開發)寫sql語句,只需要將pojp用注解跟數據庫的表和字段建立映射關系,然后在dao接口繼承Mapp類並指定泛型(你要對哪個pojo操作就指定哪個pojo),在service實現類中,直接調用相關方法,就可以執行簡單的CRUD,這樣dao接口中也不需要再寫方法了。但是這個也只能在簡單的CRUD中可以使用。

  通用Mapper其實也可以當作一種編程思維,不僅僅是dao接口可以用它抽取,service、controller也一樣可以用這種思想抽取出來,直接調用抽取出來的代碼就可以了,而不需要重復的寫一些代碼,這篇隨筆里面只說使用方式,這種思想會另起隨筆解釋。

1、添加起步依賴:

<!--通用mapper起步依賴,它內部集成了mybatis、數據源的依賴,所以加了它就可以了-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.4</version>
        </dependency>
        <!--MySQL數據庫驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis分頁插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>

2、將pojo類跟數據庫用注解建立映射關系

/****
 * @Author:admin
 * @Description:Brand構建
 * 
 *****/
@Table(name="tb_brand")//指定要映射的數據庫中的哪個表
public class Brand implements Serializable{

    
    @Id//表示該成員變量是主鍵id
    @GeneratedValue(strategy = GenerationType.IDENTITY)//標識該主鍵的策略,自增
    @Column(name = "id")
    private Integer id;//品牌id
    
    @Column(name = "name")//標識該成員變量跟數據庫中的name字段映射
    private String name;//品牌名稱
    
    @Column(name = "image")
    private String image;//品牌圖片地址
    
    @Column(name = "letter")
    private String letter;//品牌的首字母
    
    @Column(name = "seq")
    private Integer seq;//排序


    //get方法
    public Integer getId() {
        return id;
    }

    //set方法
    public void setId(Integer id) {
        this.id = id;
    }
    //get方法
    public String getName() {
        return name;
    }

    //set方法
    public void setName(String name) {
        this.name = name;
    }
    //get方法
    public String getImage() {
        return image;
    }

    //set方法
    public void setImage(String image) {
        this.image = image;
    }
    //get方法
    public String getLetter() {
        return letter;
    }

    //set方法
    public void setLetter(String letter) {
        this.letter = letter;
    }
    //get方法
    public Integer getSeq() {
        return seq;
    }

    //set方法
    public void setSeq(Integer seq) {
        this.seq = seq;
    }


}

3、但是想要使用上面這個pojo中的注解,還需要加該系列注解的依賴才能使用:

<!--(該依賴是通用mapper的注解依賴,跟數據庫的表產生映射關系)-->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
            <scope>compile</scope>
        </dependency>

4、創建controller、service、serviceImpl、dao,我按順序掛一遍:

controller:

@RestController
@RequestMapping("/brand")
public class BrandController {
    @Autowired
    private BrandService brandService;

    @GetMapping("findAll")
    public Result findBrandAll(){
        List<Brand> brandAll = brandService.findBrandAll();
        return new Result(true, StatusCode.OK,"操作成功!",brandAll);
    }
}

service:

public interface BrandService {
    List<Brand> findBrandAll();
}

serviceImpl:

@Service
public class BrandServiceImpl implements BrandService {
    @Autowired
    private BrandDao brandDao;

    @Override
    public List<Brand> findBrandAll() {
        return brandDao.selectAll();

    }
}

dao:關鍵的地方到了,這個dao需要繼承Mapper類,並指定泛型(泛型指定你要操作的pojo):繼承它就行了,不需要寫方法,當它繼承了Mapper之后,調用這個dao接口的serviceImpl類中就可以調用mapper中定義好的方法,這些方法內部會拼接sql語句

public interface BrandDao extends Mapper<Brand> {

}

 

還有最關鍵的一點,就是跟mybatis使用一樣,它需要掃描dao接口:這里要要注意,使用掃描的組件必須是tk,而不能用mybatis原本的:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
//tk!!tk!!tk!!  重要的事情說三遍,這里必須使用這個包里面的MapperScan!!
import tk.mybatis.spring.annotation.MapperScan;

@SpringBootApplication//spring boot自動配置注解
@EnableEurekaClient//這是spring cloud中的eureka客戶端注解
@MapperScan(basePackages = "com.changgou.goods.dao")//指定要掃描的dao接口的包
public class GoodsServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(GoodsServiceApplication.class,args);
    }
}

 

再附加一些Mapper中的常用api介紹:

查詢所有:里面代碼就有體現,用繼承了Mapper的dao接口(以下都是這樣,不重復寫了).select()

根據主鍵id查詢:selectByPrimaryKey(id);

添加數據:有兩個api

      .insertSelective(brand);   添加數據,如果添加的數據中有為null的字段,則不進行更改  一般都用這種方式比較好,如果有特需,則用下面方式

      .insert(brand);     添加數據,不管要添加的數據是否為null,都進行更改,如果為null則將數據庫中的該字段修改為null

根據id更新數據:跟添加數據一樣,只不過把snsert換成update就行了,同樣有兩個api,解釋同上,這里唯一要注意的就是根據id更新數據,那么傳入的pojo對象中的id字段一定要有值,否則它不知道修改哪條數據

根據id刪除數據:.deleteByPrimaryKey(id);

根據條件查詢數據:這個就要復雜一些了,這個根據條件查詢和分頁查詢放一起單獨掛:

 

根據條件查詢數據:(這里是根據兩個條件,第一個條件是name的模糊查詢,第二個是letter的條件查詢,兩個條件可能沒有,也可能只有一個,或者兩個都有)

    /**
     * 根據搜索條件查詢
     * */
    @Override
    public List<Brand> searchBrand(Brand brand) {
        //第二步:NEW出這個對象,指定存放條件內容的pojo,自動生成代碼它是object接收的,所以要轉換成Example
        Example example = new Example(Brand.class);
        //第三步,用剛剛NEW出的類創建條件對象,給這個條件對象設置條件就好了
        Example.Criteria criteria = example.createCriteria();
        //第四步,要進行非空判斷,這里用的是StringUtils做的非空判斷,
        //並且是SpringBoot的StringUtils,只要參數為null就會進入判斷,所以下面取非就是只要不為null就進入判斷執行代碼
        if (!StringUtils.isEmpty(brand)){
            //這里做判斷是因為兩個條件,如果有其中一個沒有值,說明客戶端只傳來一個,另一個條件就不添加
            if (!StringUtils.isEmpty(brand.getName())){
                //相當於sql語句:select * from t_brand <where> and name like '%'#{"name"}'%'</where>
                criteria.andLike("name","%"+brand.getName()+"%");
            }
            //這里做判斷是因為兩個條件,如果有其中一個沒有值,說明客戶端只傳來一個,另一個條件就不添加
            if (!StringUtils.isEmpty(brand.getLetter())){
                //相當於sql語句:select * from t_brand <where> and letter = #{"name"}</where>
                criteria.andEqualTo("letter",brand.getLetter());
            }
        }
        //如果以上判斷都沒有進入,說明沒有條件,那么查詢的就是所有數據

        //第一步:用dao接口調用Mapper的selectByExample方法,它需要一個類作為參數,所以第二步就new出這個對象
        List<Brand> brandList = brandDao.selectByExample(example);
        return brandList;
    }

它基本的步驟就是代碼里面的第一步到第三步,自己設置一下條件對象,然后手動進行是否有條件的判斷就好了。

 

然后就是分頁查詢,也比較簡單:只不過需要添加PageHelper的依賴,它也被spring boot集成了,所以可以添加starter的PageHelper依賴,就可以用了,不需要自己配置

    /**
     * 分頁查詢所有數據
     * */
    @Override
    public PageInfo<Brand> findPage(Integer page, Integer size) {
        //調用PageHelper的startPage方法,設置當前頁、每頁條數
        PageHelper.startPage(page,size);
        //調用dao接口繼承的Mapper方法,查詢所有的數據
        List<Brand> brandList = brandDao.selectAll();
        //把查到的數據封裝到PageInfo中,然后返回,PageInFo中包含了所有的數據,總條數等等
        PageInfo<Brand> brandPageInfo = new PageInfo<>(brandList);
        //返回即可
        return brandPageInfo;
    }

 

最后,在很多場景下,根據條件查詢的數據也需要進行分頁,不僅僅前端需要傳當前頁和每頁條數的參數,還需要傳條件過來,所以跟上面不一樣的是,前端要發送post請求為好,上面發get請求就可以:

這個就是將分頁查詢和根據條件查詢結合起來就可以了,代碼示范如下:(只要上面兩個看明白了,這個就會無師自通)

    /**
     * 根據條件分頁查詢
     * */
    @Override
    public PageInfo<Brand> cearchPageByTerm(Integer page, Integer size,Brand brand) {
        //0、如果前端沒有傳入當前頁和每頁條數,則給它賦值
        if (page==null){
            page=1;
        }
        if (size==null){
            size=10;
        }
        //1、設置當前頁、每頁條數
        PageHelper.startPage(page,size);
        //2、查詢數據
        Example example = new Example(Brand.class);
        Example.Criteria criteria = example.createCriteria();
        if (!StringUtils.isEmpty(brand)){
            if (!StringUtils.isEmpty(brand.getName())){
                criteria.andLike("name","%"+brand.getName()+"%");
            }
            if (!StringUtils.isEmpty(brand.getLetter())){
                criteria.andEqualTo("letter",brand.getLetter());
            }
        }
        List<Brand> brandList = brandDao.selectByExample(example);
        //將查詢到的數據封裝到pageinfo中
        PageInfo<Brand> listPageInfo = new PageInfo<>(brandList);
        return listPageInfo;
    }

 

 最后附加一個全局處理異常的方法

 這里面用的注解都是spring里面的,所以也並不需要添加其它的依賴,只要你有spring 或者 spring boot的依賴就可以了

//添加注解,交給spring容器,這個注解還標識這是一個全局異常處理類
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 寫一個方法,表示只要出現指定的某種異常,就進入到這個方法中進行處理
     * @ResponseBody: 因為前端只能接收JSON數據,不能直接返回Result對象,所以需要添加這個注解
     * @ExceptionHandler(value = Exception.class): 表示這個方法是全局處理異常的方法
     *                    這里面value值,要指定出現什么異常進入下面的方法,如果不指定默認就是Exception
     * */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result globalExceptionHandler(Exception ex){
        //捕獲異常並封裝到result中返回
        return new Result(false, StatusCode.ERROR,ex.getMessage());
    }

}

 

然后,發送請求,就可以獲取到數據了。這里比較簡單,就是熟練度的問題了,當然,看關鍵部位就可以了,不要嘗試直接復制搭建,這是我從微服務項目中拷貝了一部分代碼,還有很多環境配置這里沒有復制上來。

 


 

當然,除了通用mapper(也就是dao)之外,service、controller的CRUD也基本上代碼一致,所以我們也可以抽取出來,在微服務架構中,一般是單獨抽取到一個微服務,然后在各個模塊的controller、service中就可以不用寫那些重復代碼,直接繼承一個抽象類(該抽象類實現了一個核心接口,該核心接口繼承了CRUDP等五個增刪改查分頁查詢功能的接口),這樣就省下了很多重復代碼的編寫。

 

通用service代碼抽取

 

 

 上圖大概的思路就是:在core微服務中編寫五個接口,分別實現增、刪、查、改、分頁五個功能,其中又分為查詢所有、根據條件查詢、根據主鍵id查詢等等

          然后用一個核心接口,繼承這5個接口

          再就是編寫一個抽象類,實現這個核心接口的方法

          最后,在真正功能模塊中的service接口繼承核心接口,並指定泛型為要操作的實體類

             然后在真正功能模塊中的serviceImpl(service接口的實現類)先繼承core微服務中實現了接口的抽象類,並指定泛型(要操作的實體類),然后再實現真正模塊中的service接口(這個不是core工程中的核心接口),並在下面用super的方式給父類成員變量賦值

 

 

代碼實現:

1、先創造一個微服務core,打包方式為pom,再在這個微服務中創建子工程core-service,打包方式jar,並添加相關依賴(通用Mapper、mysql、pagehandler、微服務的話pojo所在工程的依賴,這些依賴一定要有,其它的視情況定,這里偷個懶,直接從項目中拷貝了依賴)

<dependencies>
        <!--對changgou-common的依賴-->
        <dependency>
            <groupId>com.changgou</groupId>
            <artifactId>changgou-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--通用mapper起步依賴-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.4</version>
        </dependency>
        <!--MySQL數據庫驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis分頁插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>
<!--web起步依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--redis 使用-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--spring-cloud-feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--eureka客戶端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--微信支付-->
        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>
        <!--httpclient支持-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
    </dependencies>

 

2、在core工程中創建包:com.xxx.core.service,在包內創建五個CRDUP接口,根據需求實現相關功能:

/***
 * 描述
 */
public interface UpdateService<T> {

    /**
     * 根據對象進行更新
     *
     * @param record
     * @return
     */
    int updateByPrimaryKey(T record);
}
/**
 * 描述
 *
 */
public interface SelectService<T> {

    /**
     * 查詢所有
     *
     * @return
     */
    public List<T> selectAll();

    /**
     * 查詢一個對象
     *
     * @param id
     * @return
     */
    public T selectByPrimaryKey(Object id);

    /**
     * 根據條件查詢
     *
     * @param record
     * @return
     */
    public List<T> select(T record);


}

 

/**
 * 描述
 */
public interface PagingService<T> {

    /**
     * 查詢所有並分頁
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    PageInfo<T> findByPage(Integer pageNo, Integer pageSize);


    /**
     * 根據查詢條件 record 分頁查詢
     *
     * @param pageNo
     * @param pageSize
     * @param record
     * @return
     */
    PageInfo<T> findByPage(Integer pageNo, Integer pageSize, T record);


    /**
     * 根據查詢條件exmaple來分頁查詢
     *
     * @param pageNo
     * @param pageSize
     * @param example
     * @return
     */
    PageInfo<T> findByPageExample(Integer pageNo, Integer pageSize, Object example);


}
/***
 * 描述
 */
public interface InsertService<T> {
    /**
     * 添加記錄
     * @param record
     * @return
     */
    int insert(T record);

}
/**
 * 刪除相關
 */
public interface DeleteService<T> {

    /**
     * 根據條件刪除
     *
     * @param record
     * @return
     */
    int delete(T record);

    /**
     * 根據ID 刪除
     *
     * @param id
     * @return
     */
    int deleteById(Object id);


}

 

然后再創建一個核心接口並繼承以上五個接口:

/***
 * 描述:繼承了CRUDP五個接口的核心接口,它被一個抽象類所實現
 */
public interface CoreService<T> extends
        DeleteService<T>,
        InsertService<T>,
        PagingService<T>,
        SelectService<T>,
        UpdateService<T> {
}

 

再創建一個impl包,在包內創建一個抽象類,實現上面這個核心接口

/***
 * 描述
 * 抽象類,實現了CoreService核心接口的CRUDP功能,誰繼承這個抽象類實現誰就要提供操作的實體類,這樣這個抽象類才能知道操作哪個對象
 * 繼承這個類,需要給通用mapper和操作的實體類賦值,通過super方式
 */
public abstract class CoreServiceImpl<T> implements CoreService<T> {
    //通用mapepr
    protected Mapper<T> baseMapper;
    //操作的實體類
    protected Class<T> clazz;

    //提供構造方法,方便它的子類給通用mapper和操作的實體類賦值
    public CoreServiceImpl(Mapper<T> baseMapper, Class<T> clazz) {
        this.baseMapper = baseMapper;
        this.clazz = clazz;
    }

    //刪除數據
    @Override
    public int delete(T record) {
        return baseMapper.delete(record);
    }
    //根據id刪除數據
    @Override
    public int deleteById(Object id) {
        return baseMapper.deleteByPrimaryKey(id);
    }
    //添加數據
    @Override
    public int insert(T record) {
        return baseMapper.insertSelective(record);
    }
    //查詢所有數據
    @Override
    public List<T> selectAll() {
        return baseMapper.selectAll();
    }
    //根據主鍵id查詢數據
    @Override
    public T selectByPrimaryKey(Object id) {
        return baseMapper.selectByPrimaryKey(id);
    }
    //根據條件查詢數據,條件只能是where = ,不能是where like之類的
    @Override
    public List<T> select(T record) {
        return baseMapper.select(record);
    }
    //根據主鍵id修改數據
    @Override
    public int updateByPrimaryKey(T record) {
        return baseMapper.updateByPrimaryKeySelective(record);
    }
    //分頁查詢數據
    @Override
    public PageInfo<T> findByPage(Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<T> list = baseMapper.selectAll();
        PageInfo<T> pageInfo = new PageInfo<T>(list);
        return pageInfo;
    }
    //根據條件模糊分頁查詢數據
    @Override
    public PageInfo<T> findByPage(Integer pageNo, Integer pageSize, T record) {
        Example example = new Example(clazz);
        Example.Criteria criteria = example.createCriteria();
        Field[] declaredFields = record.getClass().getDeclaredFields();

        for (Field declaredField : declaredFields) {
            try {
                //遇到 id注解 和 transient注解 不需要進行值的設置 直接跳過。
                if (declaredField.isAnnotationPresent(Transient.class) || declaredField.isAnnotationPresent(Id.class)) {
                    //遇到
                    continue;
                }
                //屬性描述器  record.getClass()
                PropertyDescriptor propDesc = new PropertyDescriptor(declaredField.getName(), record.getClass());
                //獲取這個值  先獲取讀方法的方法對象,並調用獲取里面的值
                Object value = propDesc.getReadMethod().invoke(record);
                //Object value = propDesc.getValue(declaredField.getName());
                //如果是字符串
                if (value != null && value.getClass().getName().equals("java.lang.String")) {
                    Column columnAnnotation = declaredField.getAnnotation(Column.class);
                    //判斷如果是長度為1 則 執行=號
                    int length = columnAnnotation.length();
                    if (length == 1) {
                        criteria.andEqualTo(declaredField.getName(), value);
                    } else {
                        criteria.andLike(declaredField.getName(), "%" + value + "%");
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        PageHelper.startPage(pageNo, pageSize);
        List<T> ts = baseMapper.selectByExample(example);
        PageInfo<T> info = new PageInfo<T>(ts);
        return info;
    }
    //根據條件分頁查詢數據
    @Override
    public PageInfo<T> findByPageExample(Integer pageNo, Integer pageSize, Object example) {
        PageHelper.startPage(pageNo, pageSize);
        List<T> list = baseMapper.selectByExample(example);
        PageInfo<T> info = new PageInfo<T>(list);
        return info;
    }


}

 

這樣,通用的service就已經寫完了,只需要在使用的時候指定泛型、給父類成員變量賦值就可以了,最后在controller就可以使用這個通用service的方法完成CRUDP

功能模塊中的service接口代碼如下:

/**
 * 品牌模塊service
 * core工程抽取了service的通用代碼,所以這里繼承這個通用service接口,指定要操作的實體類即可
 * */
public interface BrandService extends CoreService<Brand> {

}

 

功能模塊中的serviceImpl實現類代碼如下:

/**
 * 品牌模塊service實現類
 * 繼承core工程中抽取的通用service的抽象實現類,並指定要操作的實體類,這個實現類實現了基本的CRUDP的方法,所以繼承它也就相當於實現了CRUDP
 * 實現本工程編寫的BrandService
 * 因為本工程dao接口中也是操作的通用mapper,所以需要將dao接口賦值給父類,完成實現
 * 還需要給父類需要操作的實體類賦值(當前所在的類為子類,它繼承的類為父類)
 * */
@Service
public class BrandServiceImpl extends CoreServiceImpl<Brand> implements BrandService{
    private BrandDao brandDao;

    @Autowired
    public BrandServiceImpl(Mapper brandDao) {
        super(brandDao, Brand.class);
    }
}

 

做到這里,開啟功能模塊就可以接收到請求並處理請求了,以后相關的單表的CRUDP操作中業務層層不再需要寫這些代碼,只需要繼承通用service即可


 

既然service可以抽取通用代碼,那么controller中的代碼也都是差不多的,所以也可以用相同思路實現,這里掛一下代碼:依賴沒掛了,它需要上面寫的core-service工作作為依賴就可以了

1、相同的在core工程中創建子工程core-controller,建好包創建5個接口:

/***
 * 描述
 */
public interface IUpdateController<T> {

    /**
     * 根據對象進行更新 根據ID
     *
     * @param record
     * @return
     */
    Result updateByPrimaryKey(T record);
}
/***
 * 描述
 */
public interface ISelectController<T> {
    //根據ID 獲取信息
    public Result<T> findById(Object id);


    //根據ID 獲取信息列表
    public Result<List<T>> findAll();
}
/**
 * 描述
 */
public interface IPagingController<T> {

    /**
     * 查詢所有並分頁
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    Result<PageInfo<T>> findByPage(Integer pageNo, Integer pageSize);


    /**
     * 根據查詢條件 record 分頁查詢
     *
     * @param pageNo
     * @param pageSize
     * @param record
     * @return
     */
    Result<PageInfo<T>> findByPage(Integer pageNo, Integer pageSize, T record);


}
/***
 * 描述
 */
public interface IInsertController<T> {
    /**
     * 添加記錄
     * @param record
     * @return
     */
    Result insert(T record);

}
/***
 * 描述
 */
public interface IDeleteController<T> {
    /**
     * 根據ID 刪除
     *
     * @param id
     * @return
     */
    Result deleteById(Object id);
}

 

2、一樣是編寫核心接口繼承上面5個接口

/***
 * 描述
 * 繼承了CRUDP五個接口的核心接口
 */
public interface ICoreController<T> extends
        ISelectController<T>,
        IInsertController<T>,
        IPagingController<T>,
        IDeleteController<T>,
        IUpdateController<T> {
}

 

3、編寫抽象類:

/***
 * 描述
 * 抽象類,該抽象類實現了有CRUDP功能的service接口,繼承它即可使用這些功能,但要給抽取的通用service對象和調用方類型賦值
 * 這里方法上用mapping做第二個請求路徑,加載類上的第一個請求路徑不放在這,由繼承它的類加,或者在方法上寫兩級請求路徑
 */

public abstract class AbstractCoreController<T> implements ICoreController<T> {

    //調用方的service
    protected CoreService<T> coreService;
    //調用方的類型
    protected Class<T> clazz;

    //通過構造方法給通用service和操作實體類賦值
    public AbstractCoreController(CoreService<T> coreService, Class<T> clazz) {
        this.coreService = coreService;
        this.clazz = clazz;
    }

    /**
     * 刪除記錄
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    @Override
    public Result deleteById(@PathVariable(name = "id") Object id) {
        coreService.deleteById(id);
        return new Result(true, StatusCode.OK, "刪除成功");
    }

    /**
     * 添加記錄
     *
     * @param record
     * @return
     */
    @PostMapping
    @Override
    public Result insert(@RequestBody T record) {
        coreService.insert(record);
        return new Result(true, StatusCode.OK, "添加成功");
    }

    /**
     * 分頁查詢記錄
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping(value = "/search/{page}/{size}")
    @Override
    public Result<PageInfo<T>> findByPage(@PathVariable(name = "page") Integer pageNo,
                                          @PathVariable(name = "size") Integer pageSize) {
        PageInfo<T> pageInfo = coreService.findByPage(pageNo, pageSize);
        return new Result<PageInfo<T>>(true, StatusCode.OK, "分頁查詢成功", pageInfo);
    }

    @PostMapping(value = "/search/{page}/{size}")
    @Override
    public Result<PageInfo<T>> findByPage(@PathVariable(name = "page") Integer pageNo,
                                          @PathVariable(name = "size") Integer pageSize,
                                          @RequestBody T record) {
        PageInfo<T> pageInfo = coreService.findByPage(pageNo, pageSize, record);
        return new Result<PageInfo<T>>(true, StatusCode.OK, "條件分頁查詢成功", pageInfo);
    }

    @Override
    @GetMapping("/{id}")
    public Result<T> findById(@PathVariable(name = "id") Object id) {
        T t = coreService.selectByPrimaryKey(id);
        return new Result<T>(true, StatusCode.OK, "查詢單個數據成功", t);
    }

    @Override
    @GetMapping
    public Result<List<T>> findAll() {
        List<T> list = coreService.selectAll();
        return new Result<List<T>>(true, StatusCode.OK, "查詢所有數據成功", list);
    }

    //更新數據
    @Override
    @PutMapping
    public Result updateByPrimaryKey(@RequestBody T record) {
        coreService.updateByPrimaryKey(record);
        return new Result(true, StatusCode.OK, "更新成功");
    }
}

 

4、然后就是使用這個通用controller,在真正的功能模塊的controller類中繼承這個抽象類,因為controller就沒有本身的接口需要實現了,所以直接繼承抽象類指定泛型即可,這里唯一不同的就是請求的映射路徑,第一個路徑在真正功能模塊的類上,第二個路徑在通用controller的抽象類上。

/**
 * 品牌模塊
 * */
@RestController
@RequestMapping("/brand")
public class BrandController extends AbstractCoreController<Brand> {

    private CoreService coreService;
    @Autowired
    public BrandController(CoreService<Brand> coreService) {
        super(coreService, Brand.class);
    }
}

 

然后就可以發送請求實驗了。

 


免責聲明!

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



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