SpringBoot2.X整合Mybatis+Thymeleaf实现增删改查(XML版)

在SpringBoot2.0整合mybatis的基础上,继续来整合XML版的mybatis,没有看多注解版可以翻翻我之前发的文章,不过没看过也不影响XML版本的整合。注解版的整合使用场景个人理解就是比较简单的单表查询,当涉及到多表和比较的复杂的SQL语句时就会显得注解写SQL比较长,专业术语就是冗余,而在XML版的可以解决这个问题,所以我们在实际开发过程中要根据场景的需求来选择合适版本mybatis整合

案例实现的效果

在这里插入图片描述

在已有SpringBoot2.X整合Mybatis实现增删改查(注解版)的基础上,利用单元测试完成增删改查,同时利用layui后台布局+layui的table组件实现页面查询所有学生的数据渲染,可以说是简单地搭建了一个学生管理系统的布局

案例整合思路及步骤

整合思路
  1. 实现mybatis的Mapper接口的增删查改方法,并通过单元测试这四个方法
  2. 增删查改的方法通过单测后,继续编写Service,ServiceImpl和Controller层的业务逻辑
  3. 整合SpringBoot官方推荐的thymeleaf整合layUI
  4. 封装符合layui组件数据格式的VO对象,并序列化JSON对象输出到页面,页面获取JSON对象后渲染数据显示
案例目录结构

在这里插入图片描述

pom.xml
		<!--SpringBoot 官方推荐的模板引擎-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--SpringBoot 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.1.1</version>
        </dependency>
        <!--mysql驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

Demo中总共需要引入thymeleaf,web,mybatis,mysql,lombok这五个依赖,lombok是简化JavaBean书写的,其他的在具体文件中都有详细的注释,放心使用,目的就是简化和对新手友好

domain层
@Data
@NoArgsConstructor
public class Student {
    private Integer id;
    private String name;
    private Integer age;
}
mapper层
@Mapper
public interface StudentMapper {
	//查询所有学生
    List<Student> findAllStudent();
	//添加学生
    Integer insertStudent(Student student);
	//更新学生
    Integer updateStudent(Student student);
     //根据ID删除学生
    Integer deleteStudentById(Integer id);
}

这里需要提醒一下,注意@mapper注解是用来告知mybatis扫描哪个接口来构建SqlSessionFactory,因为我这里只有一个StudentMapper接口,所以我在StudentMapper接口使用@Mapper也可以实现mapper扫描功能,但当XXXMapper接口有多个时候,建议在SpringBoot启动类使用@MapperScan告知具体的包名,一劳永逸防止出错

Resources.mapper包下StudentMapper.xml
<?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.luojay.mybatisxml.mapper.StudentMapper">
    <select id="findAllStudent"  resultType="com.luojay.mybatisxml.domain.Student">
        select * from student;
    </select>
    <insert id="insertStudent" parameterType="com.luojay.mybatisxml.domain.Student">
        insert into student(name,age)values(#{name},#{age});
    </insert>
    <update id="updateStudent" parameterType="com.luojay.mybatisxml.domain.Student">
        update student set name=#{name} where id=#{id};
    </update>
    <delete id="deleteStudentById" parameterType="Integer">
        delete from student where id=#{id};
    </delete>
</mapper>
Mapper.xml存放位置注意事项

StudentMapper.xml其实可以放在上面的mapper包,让SpringBoot启动的时候就连同StudentMapper接口类一起扫描,但是会带来一个潜在的问题,Maven在项目打包的时候会将java目录下的xml资源忽略掉,所以如果StudentMapper.xml放在包下,需要在pom.xml文件中再添加如下配置,避免Maven打包时自动忽略掉XML文件

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
</build>

如果mapper.xml不放在Java目录下的,还可以放在类路径下自定义的包,不过需要在配置文件中指定扫描的文件夹位置,本文就是采用这种方式,具体的配置方式如下

#mybatis配置信息
mybatis:
  # 映射文件的路径
  mapper-locations: classpath:mapper/*.xml
  # 类型别名包配置,只能指定具体的包,多个配置可以使用英文逗号隔开
mapper单元测试
@SpringBootTest
@Transactional
class StudentMapperTest {
    @Autowired
    private StudentMapper studentMapper;
    @Rollback
    @Test
    void findAllStudent() {
        List<Student> studentList = studentMapper.findAllStudent();
        for (Student student:studentList){
            System.out.println(student);
        }
    }
    @Rollback
    @Test
    public void insertStudent(){
        Student student = new Student();
        student.setName("简书CodeLuoJay");
        student.setAge(23);
        Integer rowResult = studentMapper.insertStudent(student);
        Assertions.assertEquals(1,rowResult);//junit5的新断言
    }
    @Rollback
    @Test
    public void updateStudent(){
        Student student = new Student();
        student.setId(8);
        student.setName("博客园CodeLuoJay");
        student.setAge(23);
        Integer rowResult = studentMapper.updateStudent(student);
        Assertions.assertEquals(1,rowResult);
    }
    @Rollback
    @Test
    public void deleteStudent(){
        Integer rowResult = studentMapper.deleteStudentById(5);
    }
}

写完Mapper接口,我一般都会写一个Mapper的测试类,测试通过后再往service和controller层继续写下去,这样可以快速检测前面的编码的逻辑是否正确,新版的Junit5单元测试中不用再写Runwith(SpringRunner.class),只要写这个@SpringBootTest注解即可实现和junit4一样的效果,@Transactional与@Rollback 注解配合使用,是在测试的时候不污染数据库,当测试通过后不会往数据库添加数据,如果需要往数据库添加数据可以去掉这两个注解

service层
public interface StudentService {
    /***
     * 查询所有学生
     * @return
     */
    List<Student> findAllStudent();
}

Service层只写了一个查询所有的学生方法,跑通一个方法后,其他的增删改的方法依葫芦画瓢在这里添加就好

service.Impl包
@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentMapper studentMapper;
    @Override
    public List<Student> findAllStudent() {
        return studentMapper.findAllStudent();
    }
}

StudentServiceImpl就是IOC依赖注入StudentMapper,调用StudentMapper的接口方法即可,逻辑很简单

controlle包
@Controller
public class StudentController {
    @Autowired
    private StudentService studentService;

    // 成功输出的所有学生结果
    @ResponseBody
    @GetMapping("/getStudents")
    public ResultVO getAllStudents(){
        List<Student> studentList = studentService.findAllStudent();
        return ResultVOUtil.success(studentList);
    }
	// 跳转到所有学生的列表页面
    @GetMapping("/list")
    public String index(){
        return "list";
    }
	// 模拟跳转到后台管理员首页
    @GetMapping("/admin")
    public String admin(){
        return "admin";
    }
}

StudentController使用@controller配合@ResponseBody 输出JSON对象数据到页面,不用@RestController

是因为我在这个类中定义页面跳转,当然也可以配置一个视图解析器来实现页面跳转,但这里页面跳转不多,所以就偷个懒,在Controller中写页面跳转。 ResultVO是封装的视图对象,用于返回存储实体类对象的数据。ResultVOUtil是封装两个设置JSON数据的方法

vo包
@Data
public class ResultVO<T>{
    private String msg;
    private Integer code;
    private T data;//泛型数据
}

这是一个VO:ViewObject对象,封装这个对象是为了后面输出JSON对象与LayUI的官方的数据对应格式, 其中data封装成泛型是为了灵活处理格式,例如List,Map,Object等对象时都可以灵活处理,这里是主要用来存储从数据查出的List 数据

utils包
public class ResultVOUtil {
    //处理成功返回的对象数据封装
    public static ResultVO success(Object object){
        ResultVO resultVO = new ResultVO();
        resultVO.setData(object);
        resultVO.setCode(0);
        resultVO.setMsg("success");
        return resultVO;
    }
    //处理成功返回的空对象的数据的封装
    public static ResultVO success(){
        return success(null);
    }
    //处理错误返回的对象数据的封装
    public static ResultVO error(Integer code,String message){
        ResultVO resultVO = new ResultVO();
        resultVO.setCode(code);
        resultVO.setMsg(message);
        return resultVO;
    }
}

这是一个工具类,生成两个方法success和error方法,其中重载一个success,data输出为null时调用,目的是在序列化Json对象时方便调用

templates
<table class="layui-hide" id="demo"></table>
<script src="https://www.layuicdn.com/layui/layui.js" charset="utf-8"></script>
<!-- 注意:如果你直接复制所有代码到本地,上述js路径需要改成你本地的 -->
<script>
    layui.use('table', function(){
        var table = layui.table;

        //展示已知数据
        table.render({
            elem: '#demo'
            ,url:'/getStudents'
            ,cols: [
                    [
                        {field:'id',  title: 'id'},
                        {field:'name', title: '用户名'}
                        ,{field:'age',  title: '年龄'}
                    ]
            ]
        });
    });
</script>

我在templates中放两个页面渲染,分别是后台的admin.html和list.html页面,这两个页面的数据渲染都是一样的原理,利用CDN加速在线引入CSS,JS,完成简单页面的渲染,输出的格式与官方的table组件约定的数据格式一致,就能完成表格渲染。

//官方约定的数据格式
{
  "code": 0,
  "msg": "",
  "data": [{}, {}]
}
//我封装VO后渲染输出的JSON对象
{
    "msg": "success",
    "code": 0,//这个属性是必须要的
    //这个就是上面封装VO对象的内容
    "data": [
        {
            "id": 1,
            "name": "luojay",
            "age": 20
        },
        {
            "id": 2,
            "name": "bobi8344Student",
            "age": 22
        }
    ]
}
测试结果

在这里插入图片描述

页面渲染内容

在这里插入图片描述

利用PostMan测试数据输出没问题,便可以进行页面数据的组装和渲染了

在这里插入图片描述

源码下载

🔨Github: springboot-mybatis-xml

如果文章对你有帮助,请给个star!
关注我的公众号可以获取更多SpringBoot2.0系列资料和视频
博客园:Codeluojay
简书:Codeluojay
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值