第5章 访问数据库(MyBatis框架)

整合MyBatis框架

1.MyBatis简介

目前Java持久层最为主流的技术已经是MyBatis,它比JPA和Hibernate更为简单易用和灵活。MyBatis是支持定制化SQL、存储过程和高级映射的持久层框架。MyBatis的配置文件包括两大部分:一是基础配置文件,一个是映射文件。

首先,引入关于MyBatis的starter:

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

mybatis-spring-boot-starter是由MyBatis社区开发,先来了解MyBatis的配置和基础。

2.MyBatis的配置

MyBatis是一个基于SqlSessionFactory构建的框架,SqlSessionFactory生成SqlSession接口对象,这是MyBatis的核心。MyBatis应用的生命周期中理应只存在一个SqlSessionFactory对象,且使用单例模式(什么是单例模式:https://blog.csdn.net/qq_38379983/article/details/89893541)。而构建SqlSessionFactory是通过配置类(Configuration)来完成的,我们可以在配置文件application.properties中进行configuration配置。下图是Configuration可以配置的内容:

其中的typeHandler是MyBatis的重要配置之一,在MyBatis写入和读取数据库的过程中对于不同的数据类型(对Java来说是JavaType,对于数据库来说是JdbcType)进行自定义转换。一般来说,typeHandler的使用集中在枚举类型上。

objectFactory一般使用MyBatis默认提供的对象工厂类(DefaultObjectFactory)即可。

下面通过一个例子看MyBatis的使用流程:

首先,在用户类使用MyBatis别名,即Aliases:

/**** imports ****/
// 标明是一个实体类
@Entity(name = "user")
// 定义映射的表
@Table(name = "t_user")
@Alias(value = "user")// MyBatis指定别名
public class User {
	// 标明主键
	@Id
	// 主键策略,递增
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id = null;

	// 定义属性和表的映射关系
	@Column(name = "user_name")
	private String userName = null;

	private String note = null;

	// 定义转换器
	@Convert(converter = SexConverter.class)
	private SexEnum sex = null;

/****setter and getter****/

通过注解@Aliases指定别名为"user",同时,属性中有一个枚举,在MyBatis体系中,枚举可以通过typeHandler进行转换。

性别typeHandler:

/**** imports ****/
// 声明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 cs, int idx)
            throws SQLException {
        int sex = cs.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());
    }
}

在MyBatis中对于typeHandler的要求是实现TypeHandler<T>接口,这里直接继承抽象类BaseTypeHandler<T>实现TypeHandler<T>接口。注解@MapperJdbcTypes声明JdbcType为数据库的整型,@MappedTypes声明JavaType为SexEnum,这样MyBatis就可以对对应的数据类型进行转换了。

为了是这个User类能够与数据库的数据对应,还需要提供一个映射文件(UserMapper.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.springboot.chapter5.dao.MyBatisUserDao">
    <select id="getUser" parameterType="long" resultType="user">
        select id, user_name as userName, sex, note from t_user where id = #{id}
    </select>
</mapper>

这里<mapper>元素的namespace属性指定一个接口,后面会提供这个接口。<select>代表一个查询语句,id属性指代这条SQL,parameterType属性配置为long,则表示是一个长整型参数,resultType指定返回值类型,这里使用的是user别名。

为了启用这个映射文件,我们还需要一个接口(不需要实现任何类),它就是<mapper>里的namespace属性定义的MyBatisUserDAO,代码如下:

package com.springboot.chapter5.dao;

import org.springframework.stereotype.Repository;

import com.springboot.chapter5.pojo.User;

/**** imports ****/
@Repository
public interface MyBatisUserDao {
	public User getUser(Long id);
}

有了上面的内容,下面开始配置MyBatis,对映射文件、User别名和typeHandler进行配置,在application.properties中:

#MyBatis映射文件配置
mybatis.mapper-locations=classpath:com/springboot/chapter5/mapper/*.xml
#MyBatis扫描别名包,和注解@Alises联用
mybatis.type-aliases-package=com.springboot.chapter5.pojo
#配置typeHandler扫描包
mybatis.type-handlers-package=com.springboot.chapter5.typehandler
#日志配置
#logging.level.root=DEBUG
#logging.level.org.springframework=DEBUG
#logging.level.org.org.mybatis=DEBUG

日志配置为DEBUG级别,是为了更好的观察测试结果,其他的配置已由mybatis-spring-boot-starter对MyBatis启动做了默认配置。

3.Spring Boot整合MyBatis

这里使用最为简单和实用 的@MapperScan进行扫描加载MyBatis的Mapper:

/**** imports ****/
//定义Spring Boot扫描包路径
@SpringBootApplication(scanBasePackages = {"com.springboot.chapter5"})
//定义JPA接口扫描包路径
//@EnableJpaRepositories(basePackages = "com.springboot.chapter5.dao")
//定义实体Bean扫描包路径
//@EntityScan(basePackages = "com.springboot.chapter5.pojo")
@MapperScan(
	//指定扫描包
	basePackages = "com.springboot.chapter5.*",
	//指定SqlSessionFactory,如果sqlSessionTemplate被指定,则作废
	sqlSessionFactoryRef = "sqlSessionFactory",
	//指定sqlSessionTemplate,将忽略sqlSessionFactory的配置
	sqlSessionTemplateRef = "sqlSessionTemplate", 
	//markerInterface = Class.class,//限定扫描接口,不常用
	annotationClass = Mapper.class
)
public class Chapter5Application {
...
}

有一点需要注意:sqlSessionTemplateRef的优先权大于sqlSessionFactoryRef,当两者都配置后,系统优先选择sqlSessionTemplateref。


本节代码已上传github: https://github.com/lizeyang18/SpringBoot-2.x/tree/master/chapter5

学习永不止步,继续加油~

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值