• 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.

  • 相关阅读:
    django之ORM的查询优化、Ajax 06
    django 模型层(orm)05
    制作第三方SDK静态库、.framework(修正)
    iOS与HTML5交互方法总结(修正)
    进程间的几种通信方式
    CocoaPods容易出现的问题;
    2016 Mac OS 10.11 CocoaPods的安装问题
    HTML5要点_CSS(三)
    HTML5要点(二)
    HTML5要点(一)
  • 原文地址:https://www.cnblogs.com/baidawei/p/9105198.html
Copyright © 2020-2023  润新知