SpringBoot 實戰 (九) | 整合 Mybatis

一個優秀的廢人發表於2019-02-20

微信公眾號:一個優秀的廢人 如有問題或建議,請後臺留言,我會盡力解決你的問題。

前言

如題,今天介紹 SpringBoot 與 Mybatis 的整合以及 Mybatis 的使用,本文通過註解的形式實現。

什麼是 Mybatis

MyBatis 是支援定製化 SQL、儲存過程以及高階對映的優秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 程式碼和手動設定引數以及獲取結果集。MyBatis 可以對配置和原生 Map 使用簡單的 XML 或註解,將介面和 Java 的 POJOs(Plain Old Java Objects,普通的 Java 物件)對映成資料庫中的記錄。

優點:

  • 簡單易學:本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只要兩個 jar 檔案+配置幾個 sql 對映檔案易於學習,易於使用,通過文件和原始碼,可以比較完全的掌握它的設計思路和實現。
  • 靈活:mybatis 不會對應用程式或者資料庫的現有設計強加任何影響。 sql 寫在 xml 裡,便於統一管理和優化。通過 sql 基本上可以實現我們不使用資料訪問框架可以實現的所有功能,或許更多。
  • 解除 sql 與程式程式碼的耦合:通過提供 DAL 層,將業務邏輯和資料訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試。sql 和程式碼的分離,提高了可維護性。
  • 提供對映標籤,支援物件與資料庫的 orm 欄位關係對映
  • 提供物件關係對映標籤,支援物件關係組建維護
  • 提供xml標籤,支援編寫動態 sql。

缺點:

  • 編寫 SQL 語句時工作量很大,尤其是欄位多、關聯表多時,更是如此。
  • SQL 語句依賴於資料庫,導致資料庫移植性差,不能更換資料庫。
  • 框架還是比較簡陋,功能尚有缺失,雖然簡化了資料繫結程式碼,但是整個底層資料庫查詢實際還是要自己寫的,工作量也比較大,而且不太容易適應快速資料庫修改。
  • 二級快取機制不佳

準備工作

  • IDEA
  • JDK1.8
  • SpringBoot 2.1.3

sql 語句,建立表,插入資料:

CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `age` double DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `student` VALUES ('1', 'aaa', '21');
INSERT INTO `student` VALUES ('2', 'bbb', '22');
INSERT INTO `student` VALUES ('3', 'ccc', '23');
複製程式碼

pom.xml 檔案配置依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.nasus</groupId>
    <artifactId>mybatis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatis</name>
    <description>mybatis Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- 啟動 web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- mybatis 依賴 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>
        <!-- mysql 連線類 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- druid 資料庫連線池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.9</version>
        </dependency>
        <!-- lombok 外掛 用於簡化實體程式碼 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 單元測試 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
      
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.0.Final</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
複製程式碼

application.yaml 配置檔案

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
複製程式碼

實體類

import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    private Integer age;

}
複製程式碼

使用了 lombok 簡化了程式碼。

dao 層

import com.nasus.mybatis.domain.Student;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

@Mapper
public interface StudentMapper {

    @Insert("insert into student(name, age) values(#{name}, #{age})")
    int add(Student student);

    @Update("update student set name = #{name}, age = #{age} where id = #{id}")
    int update(@Param("name") String name, @Param("age") Integer age, @Param("id") Integer id);

    @Delete("delete from student where id = #{id}")
    int delete(int id);

    @Select("select id, name as name, age as age from student where id = #{id}")
    Student findStudentById(@Param("id") Integer id);

    @Select("select id, name as name, age as age from student")
    List<Student> findStudentList();
}
複製程式碼

這裡有必要解釋一下,@Insert 、@Update、@Delete、@Select 這些註解中的每一個代表了執行的真實 SQL。 它們每一個都使用字串陣列 (或單獨的字串)。如果傳遞的是字串陣列,它們由每個分隔它們的單獨空間串聯起來。這就當用 Java 程式碼構建 SQL 時避免了“丟失空間”的問題。 然而,如果你喜歡,也歡迎你串聯單獨 的字串。屬性:value,這是字串 陣列用來組成單獨的 SQL 語句。

@Param 如果你的對映方法的形參有多個,這個註解使用在對映方法的引數上就能為它們取自定義名字。若不給出自定義名字,多引數(不包括 RowBounds 引數)則先以 "param" 作字首,再加上它們的引數位置作為引數別名。例如 #{param1},#{param2},這個是預設值。如果註解是 @Param("id"),那麼引數就會被命名為 #{id}。

service 層

import com.nasus.mybatis.domain.Student;
import java.util.List;

public interface StudentService {

    int add(Student student);

    int update(String name, Integer age, Integer id);

    int delete(Integer id);

    Student findStudentById(Integer id);

    List<Student> findStudentList();

}
複製程式碼

實現類:

import com.nasus.mybatis.dao.StudentMapper;
import com.nasus.mybatis.domain.Student;
import com.nasus.mybatis.service.StudentService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentMapper studentMapper;

    /**
     * 新增 Student
     * @param name
     * @param age
     * @return
     */
    @Override
    public int add(Student student) {
        return studentMapper.add(student);
    }

    /**
     * 更新 Student
     * @param name
     * @param age
     * @param id
     * @return
     */
    @Override
    public int update(String name, Integer age, Integer id) {
        return studentMapper.update(name,age,id);
    }

    /**
     * 刪除 Student
     * @param id
     * @return
     */
    @Override
    public int delete(Integer id) {
        return studentMapper.delete(id);
    }

    /**
     * 根據 id 查詢 Student
     * @param id
     * @return
     */
    @Override
    public Student findStudentById(Integer id) {
        return studentMapper.findStudentById(id);
    }

    /**
     * 查詢所有的 Student
     * @return
     */
    @Override
    public List<Student> findStudentList() {
        return studentMapper.findStudentList();
    }
}
複製程式碼

controller 層構建 restful API

import com.nasus.mybatis.domain.Student;
import com.nasus.mybatis.service.StudentService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/Student")
public class StudentController {

    @Autowired
    private StudentService studentService;

    @PostMapping("")
    public int add(@RequestBody Student student){
        return studentService.add(student);
    }

    @PutMapping("/{id}")
    public int updateStudent(@PathVariable("id") Integer id, @RequestParam(value = "name", required = true) String name,
            @RequestParam(value = "age", required = true) Integer age){
        return studentService.update(name,age,id);
    }

    @DeleteMapping("/{id}")
    public void deleteStudent(@PathVariable("id") Integer id){
        studentService.delete(id);
    }

    @GetMapping("/{id}")
    public Student findStudentById(@PathVariable("id") Integer id){
        return studentService.findStudentById(id);
    }

    @GetMapping("/list")
    public List<Student> findStudentList(){
        return studentService.findStudentList();
    }
}
複製程式碼

測試結果

查詢全部學生資訊結果

其他介面已通過 postman 測試,無問題。

原始碼下載:github 地址

後語

以上為 SpringBoot 實戰 (九) | 整合 Mybatis 的教程,除了註解方式實現以外,Mybatis 還提供了 XML 方式實現。想了解更多用法請移步官方文件

最後,對 Python 、Java 感興趣請長按二維碼關注一波,我會努力帶給你們價值,如果覺得本文對你哪怕有一丁點幫助,請幫忙點好看,讓更多人知道。

另外,關注之後在傳送 1024 可領取免費學習資料。資料內容詳情請看這篇舊文:Python、C++、Java、Linux、Go、前端、演算法資料分享

一個優秀的廢人

相關文章