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

相关文章
相关标签/搜索