SpringBoot整合Mybatis应用

98 阅读4分钟

image.png

一、什么是mybatis

mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。

二、代码实战(学生管理系统)

1、Maven依赖

SpringBoot整合mybatis:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
    <exclusions>
        <exclusion>
            <artifactId>spring-boot-starter-logging</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>

依赖分析:

image.png

MySQL连接依赖:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope> <!--运行期-->
</dependency>

数据源(druid)依赖:

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.11</version>
</dependency>

2、dao层

代码:

@Mapper
@Repository
public interface StudentDao {

    List<StudentDO> findAll();

    StudentDO findById(@Param("id") int id);

    int save(@Param("stu") StudentDO student);
}

dao层负责进行数据库的行为交互,以上代码给出了查询、写入的接口其中 @Mapper 为mybatis注解,用于标识dao层的接口类
@Repository 为Spring注解,用于标识一个待注册的bean

3、与dao层对应的xml文件规范

StudengMapper.xml:

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">
        

主体:

(1) mapper叫根节点,根节点有个属性是namespace=""、namespace=""、的作用是映射我们mapper的全路径,在以后的使用中会自动映射成我们mapper的实现类
(2) select里面的Id=“”一般和我们StudentDao里面的方法名保持一致
(3) 返回值这里有一个专门的属性叫resultType="java.lang.Integer"
(4) 方法名和返回值都对应之后看有无参数,如果有要加上parameterType=""\

<mapper namespace="com.wzy.studentmanager.dao.StudentDao">

    <select id="findAll" resultType="com.wzy.studentmanager.model.StudentDO">
        select * from student_table
    </select>

    <!-- StudentDO findById(int id) -->
    <select id="findById" parameterType="int" resultType="com.wzy.studentmanager.model.StudentDO">
        select * from student_table where id = #{id}
    </select>

</mapper>

4、DB配置类

DB配置类替代了mybatis-config.xml的作用,二者均为配置mybatis的不同方式

整体代码:

@Slf4j
@Configuration
@MapperScan(basePackages = "com.wzy.studentmanager.dao",
        sqlSessionFactoryRef = "studentFactory")
public class studentDBconfig {
    @Primary
    @Bean(name="studentDataSource")
    public DataSource studentDataSource() throws Exception {
        Properties properties = new Properties();
        InputStream is = JdbcUtils.class.getResourceAsStream("/druid.properties");
        try {
            properties.load(is);
        } catch (Exception e) {
            log.error("datasource create error : ", e);
        }
        return DruidDataSourceFactory.createDataSource(properties);
    }
    
    @Primary
    @Bean(name="studentFactory")
    public SqlSessionFactory sqlSessionFactoryBean(@Qualifier("studentDataSource") DataSource dataSource) throws Exception{
        SqlSessionFactoryBean sessionFactoryBean=new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml"));
        org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
        config.setMapUnderscoreToCamelCase(true);
        sessionFactoryBean.setConfiguration(config);
        return sessionFactoryBean.getObject();
    }
}

@MapperScan注解

@MapperScan(basePackages = "com.wzy.studentmanager.dao",
        sqlSessionFactoryRef = "studentFactory")

basePackages指需要扫描的包含mapper接口的包
sqlSessionFactoryRef的官方解释:

/**
 * Specifies which {@code SqlSessionFactory} to use in the case that there is more than one in the spring context.
 * Usually this is only needed when you have more than one datasource.
 *
 * @return the bean name of {@code SqlSessionFactory}
 */

说明这个属性是针对包含多个数据源的情况,用于确定特定的SqlSessionFactory

数据源bean注册

    @Primary
    @Bean(name="studentDataSource")
    public DataSource studentDataSource() throws Exception {
        Properties properties = new Properties();
        InputStream is = JdbcUtils.class.getResourceAsStream("/druid.properties");

        try {
            // 装载转化为流的properties属性
            properties.load(is);
        } catch (Exception e) {
            log.error("datasource create error : ", e);
        }
        return DruidDataSourceFactory.createDataSource(properties);
    }

这里通过Properties对象读取数据源配置属性,属性具体值放在'druid.properties'

InputStream is = JdbcUtils.class.getResourceAsStream("/druid.properties");
这一行用于读取配置资源

druid.propertie具体代码:

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://81.70.203.113:3306/studentManager?serverTimezone=UTC
username=root
password=Wzy3688389..
initialSize=10
minIdle=1
maxActive=10
maxWait=10000
timeBetweenEvictionRunsMillis=6000
minEvictableIdleTimeMillis=300000
testWhileIdle=true
testOnBorrow=true
testOnReturn=true
poolPreparedStatements=true
maxPoolPreparedStatementPerConnectionSize=20
filters=stat

可以看到是kv形式的文件属性设置

SqlSessionFactory的Bean注册

    @Primary
    @Bean(name="studentFactory")
    public SqlSessionFactory sqlSessionFactoryBean(@Qualifier("studentDataSource") DataSource dataSource) throws Exception{
        SqlSessionFactoryBean sessionFactoryBean=new SqlSessionFactoryBean();
        // 配置前述的数据源
        sessionFactoryBean.setDataSource(dataSource);
        // 配置mybatis的xml文件
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml"));
        // 设置驼峰映射,注意创建org.apache.ibatis.session.Configuration对象
        org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
        config.setMapUnderscoreToCamelCase(true);
        sessionFactoryBean.setConfiguration(config);
        return sessionFactoryBean.getObject();
    }

三、餐后甜点:不使用config类注册Bean获取SqlSession对象

一个连接MySQL数据库的sql会话对象sqlSession,需要通过sqlSessionFactor()对象才能创建sqlSession。sqlSessionFactor()需要通过sqlSessionFactor()Builder()来创建出来。

image.png

  1. 先new一个SqlSessionFactoryBuilder(),得到一个返回值builder
  2. 获取我们的SqlSessionFactory,要用builder.上我们的builder()方法,通过流的形式传一个In的参数。
  3. 通过Resources.getResourceAsStream(“”)读取我们的主配置文件才能调用我们的依赖信息,在这里抛异常。这里有一个返回值nputStream in(字节流),通过字节流就可以读取
  4. 这时builder.build(in);得到哟个返回值就是SqlSessionFactory factory。
  5. 得到SqlSessionFactory factory之后,根据图片的流程就要得到我们的SqlSession。
  6. factory.openSession()打开我们的Session,就可以得到我们的Session
  7. 执行sql语句。sqlSession.getMapper(这里的mapper利用的是我们的一个反射机制,机制利用的时我们的一个接口)通过sqlSession.getMapper(PersonMapper.class)调用一个调用方法,得到一个返回值count
  8. 输出对应的返回值
  9. 关闭sqlsession

代码:

public class TestMybatis {
    @Test
    public void testHelloWorld() throws IOException {
        //1.通过流的机制获取主配置文件mybatis-config.xml的主要配置信息
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        //2.实例化SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3.调用builder对象的builder()方法,获取SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        //4.调用factory对象的openSession()方法,获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //5.调用接口的方法
        Integer count = sqlSession.getMapper(PersonMapper.class).findCount();
        //6.输出对应的返回值count
        System.out.println("count:" + count);
        //7.关闭 SqlSession
        sqlSession.close();
    }
 }