前两篇我们已经学习了JDBC的执行流程,我们也尝试了抽取公共方法的方式,减少代码冗余和复杂度,但是还是很不满意,那么今天我们就学习一下Mybatis,看看他是怎么封装,怎么运行,怎么实现的。学习之前,我们先来体验一把,就好比你买了一辆跑车,肯定是先飚几下,然后好奇它是怎么运作的,每个组件之间又是怎么协作的,再其次就要考虑怎么去改装它,所以我们今天的任务就是先结合Springboot把Mybatis运行起来,看看效果。
我们看定义配置文件,主要是数据的配置和 mybatis的简单配置,后期mybatis的复杂配置会一一道来
# 配置服务器信息
server:
port: 8080
# 配置数据库相关信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://192.168.31.33:3306/test?useUnicode=true&characterEncoding=utf-8
# 配置mybatis
mybatis:
# 设置别称
type-aliases-package: com.lwl.mybatis.day**
# 配置mapper文件
mapper-locations: classpath:mapper/**/*.xml
我们再定义一个Role类,来实现数据库映射,BaseModel类在之前已经有复用了,如果不清楚可以查看前一篇
/**
* @description: 角色信息
* @author :lwl
* @date :2020/6/25 11:12
* @version: 1.0.0
*/
@Data
@Accessors(chain = true)
public class Role extends BaseModel {
private String name;
private String remark;
@Override
public String toString() {
return "Role{" +
"name='" + name + '\'' +
", remark='" + remark + '\'' +
"} " + super.toString();
}
}
有了角色类之后,我们要定义接口,及它的实现类,都是比较简单的增删改查
import java.util.List;
public interface IRoleService {
int insert(Role role);
int update(Role role);
int delOne(long id);
Role findOne(long id);
List<Role> list();
}
@Service
public class RoleServiceImpl implements IRoleService {
@Resource
private RoleMapper roleMapper;
@Override
public int insert(Role role) {
return roleMapper.insert(role);
}
@Override
public int update(Role role) {
return roleMapper.update(role);
}
@Override
public int delOne(long id) {
return roleMapper.delOne(id);
}
@Override
public Role findOne(long id) {
return roleMapper.findOne(id);
}
@Override
public List<Role> list() {
return roleMapper.list();
}
}
Role的接口实现类中有一个RoleMapper接口类,这个类就是会操作数据库的关键,是通过代理模式,具体我们后期慢慢讲
public interface RoleMapper {
int insert(Role role);
int update(Role role);
int delOne(long id);
Role findOne(long id);
List<Role> list();
}
代码都已经写完了,我们就要再写一个sql语句的mapper.xml文件,将我们要运行的sql写在里面,通过注解的方式也可以实现,不过为了后期维护和优化,复杂的sql建议还是写在mapper.xml中,比如动态SQL、多表级联查询。
<?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.lwl.mybatis.day2.mapper.RoleMapper">
<resultMap id="BaseResultMap" type="com.lwl.mybatis.day2.domain.Role">
<id column="id" property="id"/>
<result column="create_user" property="createUser"/>
<result column="create_time" property="createTime"/>
<result column="modify_user" property="modifyUser"/>
<result column="modify_time" property="modifyTime"/>
<result column="name" property="name"/>
<result column="remark" property="remark"/>
</resultMap>
<insert id="insert" parameterType="com.lwl.mybatis.day2.domain.Role">
insert into role (name, remark, create_time) value (#{name}, #{remark}, now())
</insert>
<delete id="delOne" parameterType="long">
delete from role where id = #{id}
</delete>
<select id="findOne" parameterType="long" resultMap="BaseResultMap">
select * from role where id = #{id}
</select>
<select id="list" resultMap="BaseResultMap">
select * from role
</select>
<update id="update" parameterType="Role">
update role set name = #{name} , remark = #{remark}, modify_time = now()
where id = #{id}
</update>
</mapper>
好了,一切准备就绪了,我们再写一个测试类,让他们运行起来,看看效果
package com.lwl.mybatis.day2;
import com.lwl.mybatis.day2.domain.Role;
import com.lwl.mybatis.day2.service.IRoleService;
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.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@WebAppConfiguration
public class RoleTest {
@Autowired
private IRoleService roleService;
@Test
public void addTest() {
Arrays.stream(new int[]{1, 2, 3, 4}).forEach(r->{
Role role = new Role();
role.setName("lwl"+r).setRemark("哈哈哈哈哈 => " + r);
roleService.insert(role);
});
/**
* 运行结果:
* 2020-06-26 12:10:17 | DEBUG | main | com.lwl.mybatis.day2.mapper.RoleMapper.insert | ==>
* Preparing: insert into role (name, remark, create_time) value (?, ?, now())
*
* 2020-06-26 12:10:17 | DEBUG | HikariPool-1 housekeeper | com.zaxxer.hikari.pool.HikariPool |
* HikariPool-1 - Pool stats (total=1, active=1, idle=0, waiting=0)
*
* 2020-06-26 12:10:17 | DEBUG | main | com.lwl.mybatis.day2.mapper.RoleMapper.insert | ==>
* Parameters: lwl1(String), 哈哈哈哈哈 => 1(String)
* 2020-06-26 12:10:17 | DEBUG | main | com.lwl.mybatis.day2.mapper.RoleMapper.insert | <==
*
* Updates: 1
*/
}
@Test
public void delOne() {
int i = roleService.delOne(2);
System.out.println("运行结果:" + (i!=0));
}
@Test
public void update() {
Role role = new Role();
role.setName("噢噢噢噢").setRemark("12311415").setId(3L);
int i = roleService.update(role);
System.out.println("运行结果:" + (i!=0));
}
@Test
public void findOneTest() {
Role one = roleService.findOne(1);
System.out.println(Optional.ofNullable(one).toString());
}
@Test
public void list() {
List<Role> list = roleService.list();
System.out.println("运行结果:");
list.forEach(System.out::println);
/**
* Role{name='lwl1', remark='哈哈哈哈哈 => 1'}
* BaseModel(id=5, createUser=null,createTime=Fri Jun 26 12:10:16 CST 2020, modifyUser=null,modifyTime=null)
* Role{name='lwl2', remark='哈哈哈哈哈 => 2'}
* BaseModel(id=6, createUser=null,createTime=Fri Jun 26 12:10:16 CST 2020, modifyUser=null,modifyTime=null)
* Role{name='lwl3', remark='哈哈哈哈哈 => 3'}
* BaseModel(id=7, createUser=null,createTime=Fri Jun 26 12:10:16 CST 2020, modifyUser=null,modifyTime=null)
* Role{name='lwl4', remark='哈哈哈哈哈 => 4'}
* BaseModel(id=8, createUser=null,createTime=Fri Jun 26 12:10:16 CST 2020, modifyUser=null,modifyTime=null)
*
*/
}
}
如果运行过程中出现找不到RoleMapper这类的时候,请在启动类上加上mapper的扫描注解,其中@MapperScan 扫描包的范围不能太大,太大的话会到期其他类被多次注入,这样又会出去其他问题,比如测试类中的 private IRoleService roleService; 会出现多个
@SpringBootApplication
@MapperScan("com.lwl.mybatis.day2.mapper")
public class LwlMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(LwlMybatisApplication.class, args);
}
}