SpringBoot系列(五)Mybatis整合完整詳細版
SpringBoot系列(五)Mybatis整合
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是可以起到一個相同的作用。根據包名就可以看到,他們不是一個包裡面的。區別如下:
- @Autowired預設按型別裝配,預設情況下必須要求依賴物件必須存在,如果要允許null值,可以設定它的required屬性為false,如:@Autowired(required=false) ,這個註解是屬於spring的,如果我們想使用名稱裝配可以結合 @Qualifier 註解進行使用。
- @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整合就到這裡,有興趣的可以 wx search 全棧學習筆記 ,給個關注,精彩美文每天推送到你的手中