springboot下mybatis的應用

做爲一個前端開發者和僞後臺開發者先後端的技術都須要瞭解一些。早些時候作Java開發的時候主要用到的是SSH框架,對於SSM瞭解不是不少。以前的博客中寫了一些關於springboot的總結,深深地被springboot的簡化配置吸引,最近出差有時間繼續完善一下springboot系列。以前提到了springboot的helloworld的建立、三層架構的搭建、spring security的應用。上面三個掌握了以後就能夠搭建一個簡單springboot開發框架,用來練手是很不錯的。如今咱們進行逐個細化,這裏的細化不是說教技術點,而是根據開發需求來,用到什麼說什麼。先從ORM框架Mybatis提及吧。

1. spring-boot環境下建立一個mybatis項目

很簡單,打開dos,使用spring init命令建立一個springboot項目。以下:前端

$ spring init -g=com.briup.apps -a=app03 -d=mybatis,mysql app03
$ cd app03
$ mvn install

上面意思表示maven項目的組ID爲com.briup.apps ,artifactID爲app03,依賴mybatis和mysql驅動,項目名稱爲app03。項目建立完成後進入到app03目錄下,爲app03安裝所須要的依賴
這樣,就建立了一個app03的項目,而後經過eclipse打開該項目便可。java

clipboard.png

這時候若是直接運行項目,將會報錯,提示數據源配置出錯。這個問題在搭建三層架構的章節中提到過,解決方案是在application.properties文件中添加以下配置mysql

#數據源相關參數的配置
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/poll2.0
spring.datasource.username=root
spring.datasource.password=root

#mybatis映射地址的位置
mybatis.mapper-locations= classpath:/mapper/**/*.xml

2. 搭建項目結構

2.1 數據建模

在常見的數據模型中,一對多關係和多對多關係是最爲經常使用的關係,因此我這裏測試採用的案例是大學《數據庫系統概論》 教程中的案例,班級,學生,課程之間的關係,具體以下圖:spring

clipboard.png
根據如上ER圖,建表sql

-- ----------------------------
-- Table structure for tbl_clazz
-- ----------------------------
DROP TABLE IF EXISTS `tbl_clazz`;
CREATE TABLE `tbl_clazz` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for tbl_course
-- ----------------------------
DROP TABLE IF EXISTS `tbl_course`;
CREATE TABLE `tbl_course` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `credit` int(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for tbl_sc
-- ----------------------------
DROP TABLE IF EXISTS `tbl_sc`;
CREATE TABLE `tbl_sc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `student_id` int(11) DEFAULT NULL,
  `course_id` int(11) DEFAULT NULL,
  `score` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `student_id` (`student_id`),
  KEY `course_id` (`course_id`),
  CONSTRAINT `tbl_sc_ibfk_1` FOREIGN KEY (`student_id`) REFERENCES `tbl_student` (`id`) ON DELETE SET NULL,
  CONSTRAINT `tbl_sc_ibfk_2` FOREIGN KEY (`course_id`) REFERENCES `tbl_course` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for tbl_student
-- ----------------------------
DROP TABLE IF EXISTS `tbl_student`;
CREATE TABLE `tbl_student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `gender` varchar(255) DEFAULT NULL,
  `clazz_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `clazz_id` (`clazz_id`),
  CONSTRAINT `tbl_student_ibfk_1` FOREIGN KEY (`clazz_id`) REFERENCES `tbl_clazz` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

2.2 ORM映射

搭建項目結構,而且根據表結構建立類
clipboard.png數據庫

由於是對mybatis的學習,因此這裏我重點寫了bean和dao,也就是對於數據訪問層的剖析測試。json

//班級類
public class Clazz {
    private Long id;
    private String name;
    //對應的setters,getters
}

//課程類
public class Course {
    private Long id;
    private String name;
    private Integer credit;
    //對應的setters,getters
}

//學生類
public class Student {
    private Long id;
    private String name;
    private String gender;
    private Long clazz_id;
    //對應的setters,getters
}

//學生選課類
public class StudentCourse {
    private Long id;
    private Long student_id;
    private Long course_id;
    //對應的setters,getters
}

2.3 dao層代碼編寫 、mybatis的應用

在mybatis中,咱們只須要提供映射接口和映射文件便可,而事務的處理和SqlSession的處理咱們交給springBoot便可,這種方式能夠使得咱們很快的構建數據訪問層的代碼。後端

2.3.1 簡單單表的增刪改查操做

package com.briup.apps.app03.dao;

import java.util.List;

import com.briup.apps.app03.bean.Student;

public interface StudentMapper {
    List<Student> findAll();
    
    Student findById(long id);

    void save(Student student);
    
    void update(Student student);
    
    void deleteById(long id);
}

查看mybatis官方網站能夠知道,實現增刪改查須要在xml中提供對應的select,insert,update,delete元素,id名稱與映射接口中定義的方法名稱相同,resultType屬性表示返回值類型,parameterType表示參數類型。還有更多其餘屬性的解釋能夠參照官方文檔springboot

<?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.briup.apps.app03.dao.StudentMapper">
  <!-- 查詢全部學生  -->
  <select id="findAll" resultType="com.briup.apps.app03.bean.Student">
    select * from tbl_student
  </select>

  <!-- 經過ID查詢學生信息  -->
  <select id="findById" resultType="com.briup.apps.app03.bean.Student">
    select * from tbl_student where id = #{id}
  </select>
  
  <!-- 保存學生信息 -->
  <insert id="save" parameterType="com.briup.apps.app03.bean.Student">
      insert into tbl_student values(null,#{name},#{gender},#{clazz_id})
  </insert>
  
  <!-- 修改學生信息 -->
  <update id="update" parameterType="com.briup.apps.app03.bean.Student">
      update tbl_student set name = #{name}, gender = #{gender} ,clazz_id = #{clazz_id} where id = #{id}
  </update>
  
  <!-- 經過id刪除學生信息 -->
  <delete id="deleteById" parameterType="long">
      delete from tbl_student where id = #{id}
  </delete>
</mapper>

2.3.2 簡單多對一的查詢

不少時候單表的增刪改查並不能知足項目需求,好比,在查詢學生信息的時候咱們不單單須要拿到clazz_id這個外鍵,咱們還須要知道該學生所在的班級名稱,這樣就須要用到多表查詢。
一個學生對應一個班級,爲了可以映射查詢結構,這裏咱們須要先從新定義一個POJO類,來表示這種多對一關係。
以下:mybatis

package com.briup.apps.app03.bean.vm;

import com.briup.apps.app03.bean.Clazz;
import com.briup.apps.app03.bean.Student;

public class StudentVM {
    //學生信息
    private Student student;
    //學生對應的班級信息
    private Clazz clazz;
    //setters getters    
}
package com.briup.apps.app03.dao.extend;

import java.util.List;

import com.briup.apps.app03.bean.vm.StudentVM;

public interface StudentVMMapper {
    List<StudentVM> findAll();
}
<?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.briup.apps.app03.dao.extend.StudentVMMapper">
  <!-- 查詢全部學生  -->
  <select id="findAll" resultMap="studentVMResultType">
    select 
        s.id as s_id,
        s.name as s_name,
        s.gender,
        c.id as c_id,
        c.name as c_name
    from tbl_student as s ,tbl_clazz as c
    where s.clazz_id = c.id
  </select>
  <resultMap type="com.briup.apps.app03.bean.vm.StudentVM" id="studentVMResultType">
      <association property="student" javaType="com.briup.apps.app03.bean.Student">
          <id column="s_id" property="id"/>
          <result column="s_name" property="name"/>
          <result column="gender" property="gender"/>
      </association>
      <association property="clazz" javaType="com.briup.apps.app03.bean.Clazz">
          <id column="c_id" property="id"/>
          <result column="c_name" property="name"/>
      </association>
  </resultMap>
</mapper>

這種狀況下映射文件還有另一種寫法:

<?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.briup.apps.app03.dao.extend.StudentVMMapper">
  <!-- 查詢全部學生  -->
  <select id="findAll" resultMap="studentVMResultType">
    select * from tbl_student
  </select>
  
  <resultMap type="com.briup.apps.app03.bean.vm.StudentVM" id="studentVMResultType">
      <association 
          property="student" 
          column="id" 
          javaType="com.briup.apps.app03.bean.Student" 
          select="com.briup.apps.app03.dao.StudentMapper.findById" ></association>
          
      <association 
          property="clazz"
          column="clazz_id"
          javaType="com.briup.apps.app03.bean.Clazz"
          select="com.briup.apps.app03.dao.ClazzMapper.findById"></association>
</resultMap>
  
  
</mapper>

2.3.3 簡單一對多的查詢

在開發過程當中咱們還常常遇到一對多的查詢,好比,查詢題目的時候須要查詢該題目下的全部選項的信息,查詢班級的時候級聯查詢出該班級下全部的學生信息。

pojo類

package com.briup.apps.app03.bean.vm;

import java.util.List;

import com.briup.apps.app03.bean.Student;

public class ClazzVM {
    private Long id;
    private String name;
    private List<Student> students;
    //setters getters
}

映射接口

package com.briup.apps.app03.dao.extend;

import com.briup.apps.app03.bean.vm.ClazzVM;

public interface ClazzVMMapper {
    ClazzVM findById(long id);
}

映射文件

<?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.briup.apps.app03.dao.extend.ClazzVMMapper">
  <!-- 查詢全部班級以及該班級下全部學生  -->
  <select id="findById" resultMap="clazzVMResultType">
    select * from tbl_clazz where id = #{id}
  </select>
  
  <resultMap type="com.briup.apps.app03.bean.vm.ClazzVM" id="clazzVMResultType">
      <id column="id" property="id"/>
      <result column="name" property="name"/>
      <collection 
          property="students" 
          column="id"
          javaType="ArrayList"
          ofType="com.briup.apps.app03.bean.Student"
          select="com.briup.apps.app03.dao.StudentMapper.findByClazzId"></collection>
  </resultMap>
</mapper>

3. 測試

這裏的測試我使用的是springboot的單元測試功能,以下

package com.briup.apps.app03.test;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.briup.apps.app03.bean.Student;
import com.briup.apps.app03.bean.vm.StudentVM;
import com.briup.apps.app03.dao.StudentMapper;
import com.briup.apps.app03.dao.extend.StudentVMMapper;

import net.minidev.json.JSONArray;

@RunWith(SpringRunner.class)
@SpringBootTest
public class StudentMapperTest {
    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private StudentVMMapper studentVMMapper;
    
    //@Test
    public void save(){
        Student student = new Student();
        student.setName("張三");
        student.setGender("男");
        studentMapper.save(student);
        System.out.println("--保存成功");
    }
    
    //@Test
    public void update(){
        Student student = new Student();
        student.setId(8L);
        student.setName("張三三");
        student.setGender("男");
        studentMapper.update(student);
        System.out.println("--修改爲功");
    }
    
    //@Test
    public void delete(){
        studentMapper.deleteById(8L);
        System.out.println("--刪除成功");
    }
    
    @Test
    public void test1(){
        List<Student> list = studentMapper.findAll();
        String json = JSONArray.toJSONString(list);
        System.out.println("student:"+json);
    }
    
    @Test
    public void test2(){
        List<StudentVM> list = studentVMMapper.findAll();
        String json = JSONArray.toJSONString(list);
        System.out.println("studentVM:"+json);
    }
}

4. 代碼結構

爲了使得代碼拓展性強一些,我將單表操做的類和關聯操做的類分開存放。爲了實現敏捷開發,咱們能夠使用mybatis generator來實現單表操做的pojo類,映射文件,映射接口的自動產生。

clipboard.png

相關文章
相關標籤/搜索