SpringBoot第六篇:整合通用Mapper

做者:追夢1819
原文:https://www.cnblogs.com/yanfei1819/p/10876339.html
版權聲明:本文爲博主原創文章,轉載請附上博文連接!

html

引言

  在以往的項目中,對於dao層的常規 CRUD 操做,咱們一般使用 JPA、JDBC 時會作一個所謂的 BaseDaoMapper 以減小代碼量。而通用 Mapper 恰好是這一環節的替代品,代碼更簡單,更優雅,也是 Mybatis 用的很普遍的一個插件。java

  不過須要注意的一點是,通用 Mapper 支持單表操做,不支持通用的多表聯合查詢。mysql


使用

  下面經過用增刪改查的簡單示例,演示 Mapper 的用法,本系列的demo都是按照 Java web 的項目架構來,因此仍是按照 MVC 的模式進行。不過注意,由於此處只是爲了演示最基本的功能。爲了防止捨本逐末,故代碼做了最簡單的優化,只保留最基本的功能代碼,實際業務代碼可能會複雜得多。git

  準備工做,初始化數據庫:github

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `age` int(3) NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 50 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (14, 'admin', 21);
INSERT INTO `user` VALUES (48, 'teacher', 20);
INSERT INTO `user` VALUES (49, 'student', 22);

SET FOREIGN_KEY_CHECKS = 1;

  建立 SpringBoot 項目。web

  首先,引入maven依賴(由於通用 Mapper 是創建在 Mybatis 的基礎上的,因此在引入 Mapper 以前,必須先引入Mybatis 依賴):spring

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.1.4</version>
</dependency>

  而後,配置數據庫信息:sql

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.1.88:3306/test?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=pass123

  下一步,建立實體類以做數據庫映射:數據庫

package com.yanfei1819.mybatismapperdemo.entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Created by 追夢1819 on 2019-05-07.
 */
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(generator = "JDBC") // 自增字段
    private Long id;
    private String name;
    private int age;
    // set/get 省略
}

上述的註解:apache

  • @Table(name = "user") 映射數據表名

  • @Id 主鍵id

  • @GeneratedValue(generator = "JDBC") 自增字段

    這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由數據庫內部生成的主鍵(好比:像 MySQL 和 SQL Server 這樣的關係數據庫管理系統的自動遞增字段)。 這種狀況對應的xml相似下面這樣:

    <insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id">
        insert into Author (username,password,email,bio)
        values (#{username},#{password},#{email},#{bio})
    </insert>
  • 若是表字段與實體類屬性不一致,能夠用註解

  再下一步,建立代理接口:

package com.yanfei1819.mybatismapperdemo.dao;

import com.yanfei1819.mybatismapperdemo.entity.User;
import tk.mybatis.mapper.common.Mapper;

/**
 * Created by 追夢1819 on 2019-05-07.
 */
@org.apache.ibatis.annotations.Mapper
public interface UserMapper extends Mapper<User> {

}

  該接口就是通用 Mapper 的核心部分。該接口繼承 Mapper。

  再者,建立service層接口和實現類:

package com.yanfei1819.mybatismapperdemo.service;

import com.yanfei1819.mybatismapperdemo.entity.User;

import java.util.List;

/**
 * Created by 追夢1819 on 2019-05-07.
 */
public interface UserService {
    int insertUser(User user);
    int updateUser(User user);
    int deleteUser(Long id);
    List<User> listUsers();
    User getUserById(Long id);
}

  實現類:

package com.yanfei1819.mybatismapperdemo.service.impl;

import com.yanfei1819.mybatismapperdemo.dao.UserMapper;
import com.yanfei1819.mybatismapperdemo.entity.User;
import com.yanfei1819.mybatismapperdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created by 追夢1819 on 2019-05-07.
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public int insertUser(User user) {
        return userMapper.insert(user);
    }
    @Override
    public int updateUser(User user) {
        return userMapper.updateByPrimaryKey(user);
    }
    @Override
    public int deleteUser(Long id) {
        return userMapper.deleteByPrimaryKey(id);
    }
    @Override
    public List<User> listUsers() {
        return userMapper.selectAll();
    }
    @Override
    public User getUserById(Long id) {
        return userMapper.selectByPrimaryKey(id);
    }
}

  最後,建立controller層:

package com.yanfei1819.mybatismapperdemo.web.controller;

import com.yanfei1819.mybatismapperdemo.entity.User;
import com.yanfei1819.mybatismapperdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

/**
 * Created by 追夢1819 on 2019-05-07.
 */
@RestController
public class UserController {

    @Autowired
    private UserService service;

    @GetMapping("/listUsers")
    public List<User> listUser(){
        return service.listUsers();
    }
    @GetMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Long id){
        return service.getUserById(id);
    }
    @PostMapping("/insertUser")
    public int insertUser(User user){
        return service.insertUser(user);
    }
    @PostMapping("/updateUser")
    public int updateUser(User user){
        return service.updateUser(user);
    }
    @GetMapping("/deleteUser/{id}")
    public int deleteUser(@PathVariable Long id){
        return service.deleteUser(id);
    }
}

  啓動類是:

package com.yanfei1819.mybatismapperdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//import tk.mybatis.spring.annotation.MapperScan; // 注意此處引入的jar

@SpringBootApplication
//@MapperScan("com.yanfei1819.mybatismapperdemo.db")
public class MybatisMapperDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisMapperDemoApplication.class, args);
    }
}

  要注意一點, UserMapper 接口中的 @org.apache.ibatis.annotations.Mapper 註解能夠被啓動類中的註解 @MapperScan(value = {"com.yanfei1819.mybatismapperdemo.db.*"}) 代替。

  可是這裏要注意一個坑,使用了通用 Mapper 的導入的 @MapperScan 的jar包,再也不是 import org.mybatis.spring.annotation.MapperScan;,而是 import tk.mybatis.spring.annotation.MapperScan; ,否則會報錯。

  啓動項目,可測試結果。


經常使用API

  此處列舉一些經常使用的API:

  • int insert(T record); 保存一個實體,null的屬性也會保存,不會使用數據庫默認值

    int insertSelective(T record); 保存一個實體,null的屬性不會保存,會使用數據庫默認值

  • List<T> selectAll(); 查詢所有結果

    T selectByPrimaryKey(Object key); 根據主鍵字段進行查詢,方法參數必須包含完整的主鍵屬性,查詢條件使用等號

    List<T> selectByExample(Object example); 根據Example條件進行查詢

    List<T> select(T record); 根據實體中的屬性值進行查詢,查詢條件使用等號

    T selectOne(T record); 根據實體中的屬性進行查詢,只能有一個返回值,有多個結果是拋出異常,查詢條件使用等號

    int selectCount(T record); 根據實體中的屬性查詢總數,查詢條件使用等號

  • int updateByPrimaryKey(T record); 根據主鍵更新實體所有字段,null值會被更新

    int updateByExample(@Param("record") T record, @Param("example") Object example); 根據Example條件更新實體record包含的所有屬性,null值會被更新

    int updateByPrimaryKeySelective(T record); 根據主鍵更新屬性不爲null的值

  • int deleteByPrimaryKey(Object key); 根據主鍵字段進行刪除,方法參數必須包含完整的主鍵屬性

    int delete(T record); 根據實體屬性做爲條件進行刪除,查詢條件使用等號

    int deleteByExample(Object example); 根據Example條件刪除數據


參考

  文檔一:https://mapperhelper.github.io/docs

  文檔二:https://github.com/abel533/Mapper


總結

  項目中常規的增刪改查是避免不了的,並且邏輯幾乎不變。若是每個增刪改查都寫一個方法,那冗餘代碼想必很多。即便是代碼生成器生成代碼【參考本人博客:SpringBoot第八篇:整合 MyBatis-Generator】,也是不利於代碼的拓展的。

  針對這個問題,有不少解決方案,甚至本身封裝一個通用方法,也何嘗不可(本人工做初期,項目中所用的基本都是這種解決方案)。不過在多方案中,我的仍是比較喜歡通用 Mapper,一是它與 MyBatis 無縫對接;二是代碼量極少,無需配置;固然,更重要的是,已經有現成的輪子了,何須再重複去造輪子呢?
  源碼:個人GitHub


<全文完>



相關文章
相關標籤/搜索