SpringBoot系列(五)Mybatis整合詳細版

SpringBoot系列(五)Mybatis整合

目錄

  1. mybatis簡介
  2. 項目創建
  3. entity
  4. dao
  5. service
  6. serviceImpl
  7. mapper
  8. controller

1. Mybatis簡介

 MyBatis 是一款優秀的持久層框架,它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java對象)映射成數據庫中的記錄。

 換句話說,我覺得利用mybatis整合持久層要方便很多,比起以前編寫jdbc代碼操作數據庫的一些連接,簡直不要太爽。

2. 項目創建

 創建一個簡單的具有start-web依賴的SpringBoot項目,然後添加mybatis相關的依賴。

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.2</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

 依賴下載完之後,在yml文件,也可以是properties文件裏面配置連接數據庫的相關配置。

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=GMT%2B8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

 然後我們在數據庫mybatis下面創建一個student表

CREATE TABLE `student`(
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '唯一標識id',
  `name` varchar(30) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '姓名',
  `age` int(3) NOT NULL COMMENT '年齡',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

完成項目初始配置。

3. entity 實體類代碼

/**
 * (Student)實體類
 *
 * @author 全棧學習筆記
 * @since 2020-04-14 11:39:10
 */
public class Student  {
    private static final long serialVersionUID = -91969758749726312L;
    /**
    * 唯一標識id
    */
    private Integer id;
    /**
    * 姓名
    */
    private String name;
    /**
    * 年齡
    */
    private Integer age;
}

以上省略了get,以及set方法。

4. dao層代碼

package com.example.demomybatis.dao;

import com.example.demomybatis.entity.Student;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;

/**
 * (Student)表數據庫訪問層
 *
 * @author 全棧學習筆記
 * @since 2020-04-14 11:39:18
 */
@Mapper
@Repository
public interface StudentDao {

    /**
     * 通過ID查詢單條數據
     *
     * @param id 主鍵
     * @return 實例對象
     */
    Student queryById(Integer id);

    /**
     * 查詢指定行數據
     *
     * @param offset 查詢起始位置
     * @param limit 查詢條數
     * @return 對象列表
     */
    List<Student> queryAllByLimit(@Param("offset") int offset, @Param("limit") int limit);


    /**
     * 通過實體作爲篩選條件查詢
     *
     * @param student 實例對象
     * @return 對象列表
     */
    List<Student> queryAll(Student student);

    /**
     * 新增數據
     *
     * @param student 實例對象
     * @return 影響行數
     */
    int insert(Student student);

    /**
     * 修改數據
     *
     * @param student 實例對象
     * @return 影響行數
     */
    int update(Student student);

    /**
     * 通過主鍵刪除數據
     *
     * @param id 主鍵
     * @return 影響行數
     */
    int deleteById(Integer id);

}


代碼說明:dao層屬於數據訪問層,與mybatis 的xml文件相互映射,實現SQL語句的功能。

註解說明:在dao層的類需要加上 @Mapper的註解,這個註解是mybatis提供的,標識這個類是一個數據訪問層的bean,並交給spring容器管理。並且可以省去之前的xml映射文件。在編譯的時候,添加了這個類也會相應的生成這個類的實現類。

 如果你是用的idea,在serviceImpl中使用 @Autowired注入bean的時候,idea會報錯,但是不影響運行,報錯是因爲 @mapper不是spring提供的,當需要自動注入這個bean的時候idea不能 預檢測到這個bean是否可以注入到容器中,不知道新版的idea會不會有這種問題。如果想消除這個報錯,你可以在dao層的類上面加上一個 @Repository,這個註解是spring提供的,這樣就可以預檢測到mapper的bean是可以註冊到spring容器裏面的。

 你會發現在代碼中,有的接口的參數是帶了 @Param這個註解的,有的參數是沒有這個註解的。如果你只有一個參數,這個註解可要可不要。當你有兩個及其以上的註解時,你就需要用這個註解了,不然在對應的xml文件,它分辨不出來這個參數是哪一個就會報錯,用這個註解的意思就是說標識這個參數的名稱,以便讓接受參數的一方更好的找到並利用這個值。

5. service層代碼

package com.example.demomybatis.service;

import com.example.demomybatis.entity.Student;
import java.util.List;

/**
 * (Student)表服務接口
 *
 * @author 全棧學習筆記
 * @since 2020-04-14 11:39:19
 */
public interface StudentService {

    /**
     * 通過ID查詢單條數據
     *
     * @param id 主鍵
     * @return 實例對象
     */
    Student queryById(Integer id);

    /**
     * 查詢多條數據
     *
     * @param offset 查詢起始位置
     * @param limit 查詢條數
     * @return 對象列表
     */
    List<Student> queryAllByLimit(int offset, int limit);

    /**
     * 新增數據
     *
     * @param student 實例對象
     * @return 實例對象
     */
    Student insert(Student student);

    /**
     * 修改數據
     *
     * @param student 實例對象
     * @return 實例對象
     */
    Student update(Student student);

    /**
     * 通過主鍵刪除數據
     *
     * @param id 主鍵
     * @return 是否成功
     */
    boolean deleteById(Integer id);

}

 代碼說明:這是服務層的接口,serviceImpl對應服務層接口的實現。

6. serviceImpl層代碼

package com.example.demomybatis.service.impl;

import com.example.demomybatis.entity.Student;
import com.example.demomybatis.dao.StudentDao;
import com.example.demomybatis.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * (Student)表服務實現類
 *
 * @author 全棧學習筆記
 * @since 2020-04-14 11:39:19
 */
@Service("studentService")
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentDao studentDao;

    /**
     * 通過ID查詢單條數據
     *
     * @param id 主鍵
     * @return 實例對象
     */
    @Override
    public Student queryById(Integer id) {
        return this.studentDao.queryById(id);
    }

    /**
     * 查詢多條數據
     *
     * @param offset 查詢起始位置
     * @param limit 查詢條數
     * @return 對象列表
     */
    @Override
    public List<Student> queryAllByLimit(int offset, int limit) {
        return this.studentDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增數據
     *
     * @param student 實例對象
     * @return 實例對象
     */
    @Override
    public Student insert(Student student) {
        this.studentDao.insert(student);
        return student;
    }

    /**
     * 修改數據
     *
     * @param student 實例對象
     * @return 實例對象
     */
    @Override
    public Student update(Student student) {
        this.studentDao.update(student);
        return this.queryById(student.getId());
    }

    /**
     * 通過主鍵刪除數據
     *
     * @param id 主鍵
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.studentDao.deleteById(id) > 0;
    }
}

 代碼說明:@Service標識這個bean是service層的,也就是服務層,並交給spring容器管理。參數的value屬性是這個bean的名稱,也可以不寫,默認爲類名。

 這裏我們可以說一下,@Resource@Autowired,前面我們在serviceImpl裏面需要用到dao層的方法的時候,不是直接new一個對象,在哪需要就在哪new,而是利用註解,實現自定注入裝配,利用spring容器管理這些bean,這樣寫出來的代碼是鬆耦合的,類之間的耦合度更低,維護性就相對提高了。
@Resource@Autowired是可以起到一個相同的作用。根據包名就可以看到,他們不是一個包裏面的。區別如下:

  1. @Autowired默認按類型裝配,默認情況下必須要求依賴對象必須存在,如果要允許null值,可以設置它的required屬性爲false,如:@Autowired(required=false) ,這個註解是屬於spring的,如果我們想使用名稱裝配可以結合 @Qualifier 註解進行使用。
  2. @Resource默認按照名稱進行裝配,名稱可以通過name屬性進行指定,如果沒有指定name屬性,當註解寫在字段上時,默認取字段名進行安裝名稱查找,如果註解寫在setter方法上默認取屬性名進行裝配。當找不到與名稱匹配的bean時才按照類型進行裝配。但是需要注意的是,如果name屬性一旦指定,就只會按照名稱進行裝配。這個註解屬於J2EE的

7. mapper層代碼

 所謂的mapper層,就是xml文件,與dao層對應的。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demomybatis.dao.StudentDao">
    <resultMap type="com.example.demomybatis.entity.Student" id="StudentMap">
        <result property="id" column="id" jdbcType="INTEGER"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="age" column="age" jdbcType="INTEGER"/>
    </resultMap>

    <!--查詢單個-->
    <select id="queryById" resultMap="StudentMap">
        select
          id, name, age
        from mybatis.student
        where id = #{id}
    </select>

    <!--查詢指定行數據-->
    <select id="queryAllByLimit" resultMap="StudentMap">
        select
          id, name, age
        from mybatis.student
        limit #{offset}, #{limit}
    </select>

    <!--通過實體作爲篩選條件查詢-->
    <select id="queryAll" resultMap="StudentMap">
        select
          id, name, age
        from mybatis.student
        <where>
            <if test="id != null">
                and id = #{id}
            </if>
            <if test="name != null and name != ''">
                and name = #{name}
            </if>
            <if test="age != null">
                and age = #{age}
            </if>
        </where>
    </select>

    <!--新增所有列-->
    <insert id="insert" keyProperty="id" useGeneratedKeys="true">
        insert into mybatis.student(name, age)
        values (#{name}, #{age})
    </insert>

    <!--通過主鍵修改數據-->
    <update id="update">
        update mybatis.student
        <set>
            <if test="name != null and name != ''">
                name = #{name},
            </if>
            <if test="age != null">
                age = #{age},
            </if>
        </set>
        where id = #{id}
    </update>

    <!--通過主鍵刪除-->
    <delete id="deleteById">
        delete from mybatis.student where id = #{id}
    </delete>

</mapper>

 這裏面對應了SQL的增刪改查語句,然後在dao層的方法,對應了每一個SQL語句,這裏面SQL語句的id,對應dao層的每一個接口方法。
默認的配置是檢測不到這個xml文件的,然後我們需要做以下的配置。
我把xml文件放在resources文件夾下面的dao文件夾下面。
然後我們在yml裏面加上以下配置。

mybatis:
  type-aliases-package: com.example.demomybatis.entity
  mapper-locations: classpath:dao/*Mapper.xml

8. controller層代碼

 controller層的代碼我們是用來測試的,一般也是返回數據給前端的地方。

package com.example.demomybatis.controller;

import com.example.demomybatis.entity.Student;
import com.example.demomybatis.service.StudentService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * (Student)表控制層
 *
 * @author 全棧學習筆記
 * @since 2020-04-14 11:39:20
 */
@RestController
@RequestMapping("student")
public class StudentController {
    /**
     * 服務對象
     */
    @Resource
    private StudentService studentService;

    /**
     * 通過主鍵查詢單條數據
     *
     * @param id 主鍵
     * @return 單條數據
     */
    @GetMapping("selectOne")
    public Student selectOne(Integer id) {
        return this.studentService.queryById(id);
    }

}

 代碼說明:@RestController 這個註解等效於 @Controller加上 @ResponseBody,添加了這個註解就是讓這個類返回json串,這是spring內部提供的json解析。@RequesMapping 註解是一個地址映射的註解。就是根據這個地址,可以找到這個方法,這個類,註解到類上,就相當於方法的父類地址。

 測試一下。我們先在數據庫裏面添加一條數據。

insert into student(id,name,age) VALUES(2,'全棧學習筆記',22)

 然後在瀏覽器輸入:localhost:8088/student/selectOne?id=2 就可以看到我們拿到的數據了。端口配置根據自己項目而定。

好了,這一期的mybatis整合就到這裏,下一期更精彩!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章