Spring Boot整合Mybatis

SpringBoot整合MyBatis框架

MyBatis比JPA和Hibernate更为简单易用,也更加灵活。在以系统管理为主的时代,Hibernate的模型化有助于系统的分系和建模,重点在于业务模型的分系和设计,术语表和业务模型分系的阶段。而现今已经是移动互联网的时代,互联网的特点是面对公众,相对而言业务比较简单,但是往往网站会拥有大量的用户,面对的问题主要是大数据、高并发和性能问题。因此在这个时代,互联网企业开发的难度主要集中在大数据和性能问题上,所以互联网企业更加关注的是性能和灵活性。

简介

MyBatis官方定义:MyBatis是定制化SQL,存储过程以及高级映射的优秀的持久化层框架。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以对配置和原生Map使用简单的XML或注解,将接口和JAVA的POJO(Plain Old Java Object,普通JAVA对象)映射成数据库中的记录。

可以看出MyBatis是基于一种sql到pojo的模型,它需要我们提供SQL、映射关系(XML或者注解,目前以XML为主)和pojo。但是对于sql和pojo的ing折关系,它提供了自动映射和驼峰映射等,使开发者的开发工作大大减少。

Maven依赖

        <dependency>
        	<groupId>org.mybatis.spring.boot</groupId>
        	<artifactId>mybatis-spring-boot-starter</artifactId>
        	<version>1.3.1</version>
        </dependency>

MyBatis的配置MyBatis的配置文件包括两部分

  • 基础配置文件
  • 映射文件

MyBatis是一个基于SqlSessionFactory构建的框架。对于SqlSessionFactory而言,它的作用是生成SqlSession接口对象,这个接口对象是MyBatis操作的核心。

构建SqlSessionFactory是通过配置类(Configuration)来完成的,对于mybatis-spring-boot-starter,它会给与我们在配置文件(application.properties)进行Configuration配置相关内容。

  • properties(属性):属性文件在实际应用中一般采用spring进行配置,而不是mybatis,这里不介绍。

  • settings(设置):它的配置将改变mybatis的底层行为,可以配置映射规则,如指定映射和驼峰映射,执行器(executor)类型,缓存等内容,比较复杂,具体可以参考mybatis官方网站

  • typeAliases(类型别名):因为使用类全限定名会比较长,所以mybatis会对常用的类提供默认的别名,此外还允许我们通过typeAliases配置自定义别名

  • typeHandlers(类型处理器):这是mybatis的重要配置之一,在mybatis写入和读取数据库的过程中对于不同类型的数据(对于java是JavaType,对于数据库则是JdbcType)进行自定义转换,在大部分的情况下我们不需要使用自定义的typeHandler,因为在mybatis自身就已经定义了比较多的typehandler,mybatis会自动识别javaType和jdbcType,从而实现各种类型的转换。一般来说,typeHandler主要使用集中在枚举类型上。

  • objectFactory(对象工厂):这是一个在mybatis生成返回pojo时会调用的工厂类型。一般我们使用mybatis默认提供的对象工厂类型(DafaultObjectFactory)就可以了。

  • plugins(插件):有时候也成为拦截器,是mybatis最强大也是最危险的组件,它通过动态代理和责任链模式来完成,可以修改mybatis底层的实现功能。

  • environments(数据库环境):可以配置数据库连接内容和事务,一般而言,这些交由spring托管。

  • mappers(映射器):是mybatis最核心的组件,它提供sql和pojo映射关系,这是mybatis开发的核心。

定义POJO对象

现在我们定义一个POJO

Person

package com.lay.pojo;

// MyBatis指定别名
@Alias(value = "person")
public class Person {
    private Long id = null;
    
    private String personName = null;
    
    //性别枚举,这里需要使用typeHandler进行转换
    private SexEnum sex = null;//枚举
    
    private String note = null;
    
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public String getUserName() {
        return personName;
    }
    
    public void setUserName(String personName) {
        this.personName = personName;
    }
    
    public SexEnum getSex() {
        return sex;
    }
    
    public void setSex(SexEnum sex) {
        this.sex = sex;
    }
    
    public String getNote() {
        return note;
    }
    
    public void setNote(String note) {
        this.note = note;
    }
    
}

这里通过注解@Alias(value = "person")指定了对象的别名为user,同时,person有个性别属性类型为枚举。

package com.lay.enumeration;

public enum SexEnum {
    MALE(1, "男"), FEMALE(2, "女");
    
    private int id;
    
    private String name;
    
    SexEnum(int id, String name) {
        this.id = id;
        this.name = name;
    }
    
    public static SexEnum getEnumById(int id) {
        for (SexEnum sex : SexEnum.values()) {
            if (sex.getId() == id) {
                return sex;
            }
        }
        return null;
    }
    
    public static SexEnum getEnumByName(String name) {
        for (SexEnum sex : SexEnum.values()) {
            if (sex.getName().equals(name)) {
                return sex;
            }
        }
        return null;
    }
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
}

在mybatis里,枚举是可以通过typeHandler进行转换的。

TypeHandler转换类

BaseTypeHandler<T>抽象类实现了TypeHandler<T>接口。

这里我们对性别这个枚举类通过继承BaseTypeHandler<T>类进行转换。

SexTypeHandler

package com.lay.typehandler;

//声明JdbcType为整形
@MappedJdbcTypes(JdbcType.INTEGER)
//声明JavaType为枚举SexEnum
@MappedTypes(value = SexEnum.class)
public class SexTypeHandler extends BaseTypeHandler<SexEnum> {
    
    //通过列名读取性别
    @Override
    public SexEnum getNullableResult(ResultSet rs, String col) throws SQLException {
        int sex = rs.getInt(col);
        if (sex != 1 && sex != 2) {
            return null;
        }
        return SexEnum.getEnumById(sex);
    }
    
    //通过下标读取性别
    @Override
    public SexEnum getNullableResult(ResultSet rs, int idx) throws SQLException {
        int sex = rs.getInt(idx);
        if (sex != 1 && sex != 2) {
            return null;
        }
        return SexEnum.getEnumById(sex);
    }
    
    //通过存储存储过程读取性别
    @Override
    public SexEnum getNullableResult(CallableStatement rs, int idx) throws SQLException {
        int sex = rs.getInt(idx);
        if (sex != 1 && sex != 2) {
            return null;
        }
        return SexEnum.getEnumById(sex);
    }
    
    //设置非空性别参数
    @Override
    public void setNonNullParameter(PreparedStatement ps, int idx, SexEnum sex, JdbcType jdbcType) throws SQLException {
        ps.setInt(idx, sex.getId());
    }
    
}

映射文件(xml)

为了使POJO能够与数据库的数据对应,还需要一个映射文件。

personMapper.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.lay.dao.MyBatisPersonDao">
	<select id="getPerson" parameterType="long" resultType="person">
		select id,person_name as personName,sex,note from t_person where id=#{id}
	</select>
</mapper>

这里personMapper.xml的目录结构是resources/mapper/personMapper.xml

  • namespcae:指定一个接口(DAO)
  • select:代表是一个查询语,id属性指这条sql,映射dao接口中的方法,parameterType代表参数类型,resultType代表返回类型,这里用到了pojo对象的别名。
  • 这里我们注意到 数据库person_name用了别名对应pojo属性personName保持一致性。在默认的情况下,我们可以不写,mybatis会默认按照驼峰命名规则映射。或者我们也可以自己配置。

定义mybatis操作接口(DAO)

MyBatisPersonDao

package com.lay.dao;

@Mapper
public interface MyBatisPersonDao {
    public Person getPerson(Long id);
}

注意这仅仅是一个接口,不需要任何实现类。通过配置扫描mybatis会自动装配进IoC容器实现依赖注入。

配置文件application.properties

application.properties

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot_database
spring.datasource.username=root
spring.datasource.password=123456
# spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#指定数据连接池的类型
spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
#最大等待连接中的数量,设置0为没有限
spring.datasource.dbcp2.max-idle=10
#最大连接活动数
spring.datasource.dbcp2.max-total=50
#最大等待毫秒数,单位ms,超过时间会出错误信息
spring.datasource.dbcp2.max-wait-millis=10000
#数据库连接池初始化连接数
spring.datasource.dbcp2.initial-size=5

# mybatis映射文件
mybatis.mapper-locations=classpath:mapper/*.xml
# mybatis扫描别名包,和注解@Alias联用
mybatis.type-aliases-package: com.lay.pojo
# 配置typehandler类型转换的扫描包
mybatis.type-handlers-package=com.lay.typehandler
#驼峰命名转换
mybatis.configuration.mapUnderscoreToCamelCase=true
#打印日志
logging.level.com.lay.dao:trace


扫描装配@MapperScan

SpringbootDatabaseApplication

package com.lay;

@SpringBootApplication
@MapperScan(basePackages = "com.lay.dao", annotationClass = Mapper.class)
public class SpringbootDatabaseApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(SpringbootDatabaseApplication.class, args);
    }
}

通过@MapperScan指定扫描包basePackages = "com.lay.dao",会自动装配到IoC容器中。annotationClass = Mapper.class限定被@Mapper标注的类。

测试

首先定义一个服务接口

MyBatisPersonService

package com.lay.service;

public interface MyBatisPersonService {
    public Person getPerson(Long id);
}

实现类MyBatisPersonServiceImpl

package com.lay.service.impl;

@Service
public class MyBatisPersonServiceImpl implements MyBatisPersonService {
    
    @Autowired
    MyBatisPersonDao myBatisPersonDao;
    
    @Override
    public Person getPerson(Long id) {
        return myBatisPersonDao.getPerson(id);
    }
    
}

访问控制器MybatisController

package com.lay.controller;
@Controller
@RequestMapping(value = "mybatis")
public class MybatisController {
    @Autowired
    MyBatisPersonService myBatisPersonService;
    
    @RequestMapping(value = "getPerson")
    @ResponseBody
    public Person getPerson(@RequestParam("id") Long id) {
        return myBatisPersonService.getPerson(id);
    }
    
}

然后通过浏览器地址栏输入http://localhost:8080/mybatis/getPerson?id=1进行测试

其他装配方式

  • MapperFactoryBean手动
@Configuration
public class MybatisConfig(){
	//这里的SqlSessionFactory是spring boot自动为我们生成的。
    @Autowired
    SqlSessionFactory sqlSessionFactory=null;
    
    @Bean
    public MapperFactoryBean<MyBatisPersonDao> initMyBatisUserDao(){
        MapperFactoryBean<MyBatisPersonDao> bean=new MapperFactoryBean<>();
        bean.setMapperInterface(MyBatisPersonDao.class);
        bean.setSqlSessionFactory(sqlSessionFactory);
        return bean;
    }
}
  • 使用MapperScannerConfigurer扫描装配Mybatis接口
@Bean
public MapperScannerConfigurer mapperScannerConfig(){
    //定义扫描器实例
    MapperScannerConfigurer mapperScannerConfigurer=new MapperScannerConfigurer();
    //加载SqlSessionFactory,spring boot会自动生产SqlSessionFactory实例
    mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
    //定义扫描的包
    mapperScannerConfigurer.setBasePackage("com.lay.dao");
    //限定被标注@Mapper的接口才被扫描
    mapperScannerConfigurer.setAnnotationClass(Mapper.class);
    return mapperScannerConfigurer;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值