Spring Boot (9) mybatis全注解化

ORM对比图

框架对比Spring JDBCSpring Data JpaMybatis
性能 性能最好 性能最差 居中
代码量
学习成本 居中
推荐指数 ❤❤❤ ❤❤❤❤❤ ❤❤❤❤❤

首先在pom.xml中添加引用

<!-- 引入mybatis -->  
<dependency>  
    <groupId>org.mybatis.spring.boot</groupId>  
    <artifactId>mybatis-spring-boot-starter</artifactId>  
    <version>1.3.0</version>  
</dependency>  
<!-- mybatis分页插件 -->  
<dependency>  
    <groupId>com.github.pagehelper</groupId>  
    <artifactId>pagehelper-spring-boot-starter</artifactId>  
    <version>1.1.1</version>  
</dependency>

 

基本SQL操作

  spring boot已经自动实现了mybatis所有配置,直接写dao接口即可

package com.david.dao;

import com.david.bean.Cat;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

//声明一个mybatis的dao接口,会被spring boot扫描到
@Mapper
public interface MyBatisDao {
    //声明一个查询方法,相应的增删改使用@Insert @Delete @Update
    @Select("select * from Cat where id = #{id}")
    List<Cat> findById(Cat param);
}

 

扫描Mapper

  可以在配置类加上@MapperScan("com.david.dao") 注解,扫描dao包中的所有接口,替代在每个dao中写@Mapper注解,不过这样会提高耦合度。而@Mapper可以与dao自成一体,与@Controller、@Service遥相呼应,整体结构更优雅。

 

驼峰命名

  在properties添加以下配置,在执行查询后,可以讲数据库的NN_NN格式字段在java结果集对象中自动转换成驼峰命名参数。

mybatis.configuration.mapUnderscoreToCamelCase=true

 

结果映射@Results

  如果结果集不是java对象而是map,map中的列名回合数据库中的NN_NN一样,是不会自动驼峰转换的,可以使用@Result来指明结果映射,同时也适用java对象。

@Mapper
public interface MyBatisDao {
    @Select("select * from Cat where id = #{id}")
    List<Cat> findById(Cat param);


    @Results({
            @Result(property = "catName", column = "cat_name"),
            @Result(property = "catAge", column = "cat_age")
    })
    @Select("select * from Cat")
    List<Map> findAll(Cat param);
}

 

使用List<Map>不用去维护pojo,适于用数据库字段不确定或经常变化的场景。但是程序的可读性、可维护性不如List<Cat>。

 

可复用的@Results

  声明时给id赋值为cat

public interface MyBatisDao {
    
    @Results(id="cat",value={
            @Result(property = "catName", column = "cat_name"),
            @Result(property = "catAge", column = "cat_age")
    })
    @Select("select * from Cat")
    List<Map> findAll(Cat param);

    @ResultMap("cat")
    @Select("select * from Cat where id = #{id}")
    List<Cat> findById(Cat param);

}

在其他方法中直接@ResultMap("cat")即可重复适用id为cat的结果映射

 

打印SQL日志到控制台

  在application.properties中添加以下配置

logging.level.你的包名.mybatis接口包=debug 
logging.level.org.springframework=WARN
logging.level.com.david.dao.MyBatisDao=DEBUG
#输出日志文件,默认不输出
logging.file=logs/spring-boot-logging.log
#修改日志级别,默认为INFO
logging.level.root=DEBUG

 

执行SQL时,会在控制台打印sql日志,并记录到日志里去

@RestController
public class HelloController {

    @Resource
    private MyBatisDao myBatisDao;

    @GetMapping("/findAll")
    public List<Map> findAll() {
        return myBatisDao.findAll();
    }

 

 

分页

  分页逻辑写在service层

@Service
@Transactional
public class MyBatisService {

    @Resource
    private MyBatisDao myBatisDao;


    public Page<Cat> findAll(){
        //分页插件:查询第1页,每页10行
        Page<Cat> page = PageHelper.startPage(1,10);
        myBatisDao.findAll();
        //数据表的总行数
        page.getTotal();
        //分页查询结果的总行数
        page.size();
        //第一个cat对象
        page.get(0);
        return page;
    }

}

controller

@RestController
public class HelloController {

    @Autowired
    private MyBatisService myBatisService;


    @GetMapping("/findAll")
    public Page<Cat> findAll() {
        return myBatisService.findAll();
    }

 

执行原理:PageHelper.startPage会拦截下一个sql,也就是mybatisDao.findAll()的sql。并且根据当前数据库的语法,把这个sql改造成一个高性能的分页sql,同时还会查询该表的总行数。

PageHelper.startPage最好和myBatisDao.findAll()紧跟在一起,中间不要有别的逻辑,否则可能出现bug。

Page<Cat> page:相当于一个list集合,findAll()方法查询完成后回给page对象的相关参数赋值

 

回传ID

  数据库的id主键是自增长的,添加一条数据后,想得到这条自动增长的id,在dao层添加以下代码

@Mapper
public interface MyBatisDao {
    @Insert("insert into Cat (cat_name,cat_age) values (#{catName},#{catAge})")
    @Options(useGeneratedKeys = true,keyProperty = "id")
    int insert(Cat cat);
}

useGeneratedKeys=true:获取数据库生成的主键

keyProperty="id":把主键存入Cat cat对象的id属性

service

    public int insert(Cat cat){
        return myBatisDao.insert(cat);
    }

controller

    @GetMapping("/addCat")
    public int insert(){
        Cat cat = new Cat();
        cat.setCatAge(18);
        cat.setCatName("mimi");
        myBatisService.insert(cat);
        return cat.getId(); //回传id
    }

 

存储过程

  创建一个mysql存储过程,传入一个id值,根据这个id查询出name并传出参数

CREATE DEFINER=`root`@`localhost` PROCEDURE `helloPROC`(IN id_in int,out name_out varchar(10))
BEGIN
    select cat_name into name_out from cat where id = id_in;
END

dao层

mode=IN:传入参数,就是cat.id

mode=OUT:传出参数,就是cat.catName

StatementType.CALLABLE:说明这是一个存储过程

    @Select("call helloPROC(#{id,mode=IN,jdbcType=INTEGER},#{catName,mode=OUT,jdbcType=VARCHAR})")
    @Options(statementType = StatementType.CALLABLE)
    void call(Cat cat);

service层

    public void call() {
        Cat cat = new Cat();
        cat.setId(2);
        myBatisDao.call(cat);
        System.out.print(cat.getCatName());
    }

调用方法 返回tom.

 

posted @ 2018-05-29 15:17  海盗船长  阅读(631)  评论(0编辑  收藏  举报