framwork学习笔记day02---mybatis

4 篇文章 0 订阅
4 篇文章 0 订阅
这篇博客详细介绍了MyBatis框架的优势,包括解决原始JDBC存在的问题,如连接管理、配置文件的使用、反射操作以及事务管理。文章还涵盖了SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession等核心API的介绍,以及如何进行MyBatis的传统DAO开发和接口代理开发。此外,博主还讲解了mapper文件的配置、SqlMapperConfig配置文件的内容,以及在MyBatis中如何处理事务和使用内置连接池。
摘要由CSDN通过智能技术生成

原始jdbc存在的问题

  • 存在问题

    • ①频繁地创建和销毁Connection对象
    • ②driverClass、url、username、password、sql语句都存在字符串硬编码
    • ③手动设置输入参数
      • 输入映射:将输入的值映射到占位符
    • ④手动处理结果集
      • 输出映射:将结果集映射到javabean
    • ⑤手动释放资源
  • 解决方案(使用mybatis)

    • ①引入连接池
    • ②使用配置文件
    • ③使用反射+缺省操作
    • ④使用反射+缺省操作
    • ⑤缺省操作

mybatis基本概念

  • 概述
    • mybatis是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接 等繁杂的过程
  • 结构
    • image-20211220091558392

mybatis入门程序

  • 官网
  • 开发步骤
    • ①引入mybatis相关依赖
    • ②创建mybatis的核心配置文件
      • 配置数据库环境(事务管理器、数据源)
      • 加载mapper映射文件
    • ③创建mapper映射配置文件
      • 配置MappedStatement
    • ④定义dao接口及其实现子类
      • 1,读取mybatis的核心配置文件
      • 2,创建SqlSessionFactory对象
      • 3,获取SqlSession对象
      • 4,操作对应的MappedStatement对象
      • 5,释放资源
    • ⑤代码测试
  • ①引入mybatis相关依赖
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.48</version>
</dependency>

②创建mybatis的核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <!--事务管理器-->
            <transactionManager type="JDBC"/>
            <!--数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mydb1"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--加载映射配置文件-->
    <mappers>
        <mapper resource="mapper01.xml"/>
    </mappers>
</configuration>

③创建mapper映射配置文件

<?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="test">


    <!--
        配置MappedStatement
        id:statement唯一标识
        parameterType: 输入映射的类型
        resultType: 输出映射的类型
    -->
    <select id="selectExamById" parameterType="int" resultType="com.atguigu.pojo.Exam">
        select * from tb_exam where id = #{id}
    </select>



</mapper>

④定义dao接口及其实现子类

public class ExamDaoImpl implements ExamDao {
    @Override
    public Exam selectExamById(Integer id) throws Exception {
        //1,读取mybatis核心配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2,获取SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3,打开会话
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //4,执行MappedStatement
        Exam exam = sqlSession.selectOne("selectExamById", id);
        //5,关闭会话
        sqlSession .close();
        return exam;
    }
}

⑤代码测试

public class ExamDaoTest {

    @Test
    public void selectExamById() throws Exception {

        ExamDao examDao = new ExamDaoImpl();
        Exam exam = examDao.selectExamById(1);
        System.out.println("exam = " + exam);

    }
}

mapper文件说明

  • 映射文件
    • image-20211220101926370

05-添加用户(掌握)

添加用户

代码实现

<!--添加用户-->
<insert id="addExam" parameterType="com.atguigu.pojo.Exam">
    insert into tb_exam
    values (null, #{name}, #{math}, #{english}, #{chinese})
</insert>
@Override
public int addExam(Exam inputExam) throws Exception {
    //1,读取mybatis核心配置文件
    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    //2,获取SqlSessionFactory对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //3,打开会话
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //4,执行MappedStatement
    int addExam = sqlSession.insert("addExam", inputExam);
    //5,提交事务
    sqlSession.commit();
    //6,关闭会话
    sqlSession.close();
    return addExam;
}

注意事项

  • mybatis的事务是手动提交

删除用户

代码实现

<delete id="deleteExamById" parameterType="int">
    delete
    from tb_exam
    where id = #{id}
</delete>
@Override
public int deleteExamById(Integer id) throws Exception {
    //1,读取mybatis核心配置文件
    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    //2,获取SqlSessionFactory对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //3,打开会话
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //4,执行MappedStatement
    int deleteExamById = sqlSession.insert("deleteExamById", id);
    //5,提交事务
    sqlSession.commit();
    //6,关闭会话
    sqlSession.close();
    return deleteExamById;
}

修改用户

代码实现

<update id="updateExamById" parameterType="com.atguigu.pojo.Exam">
    update tb_exam
    set name    = #{name},
        math    = #{math},
        english = #{english},
        chinese = #{chinese}
    where id = #{id}
</update>
@Override
public int updateExamById(Exam inputExam) throws Exception {
    //1,读取mybatis核心配置文件
    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    //2,获取SqlSessionFactory对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //3,打开会话
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //4,执行MappedStatement
    int updateExamById = sqlSession.insert("updateExamById", inputExam);
    //5,提交事务
    sqlSession.commit();
    //6,关闭会话
    sqlSession.close();
    return updateExamById;
}

mybatis相关API

Resources类介绍

  • 概述
    用于读取资源的工具类

SqlSessionFactoryBuilder类介绍

  • 概述
    这个类可以被实例化、使用和丢弃,一旦创建类SqlFactory,就不在需要它
    但最好不要一直保留它
    最好使用匿名创建

SqlSessionFactory接口介绍

概述

  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。

SqlSession接口介绍

  • 概述
    • 每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
    • 一次数据库操作就应该是一个新的SqlSession对象

mybatis传统dao开发

  • 概述
    • mybatis开发有两种方式:1,传统dao开发;2,mapper接口代理开发
    • 传统dao开发 : dao接口 + dao接口实现子类 + mapper映射文件
  • 代码实现
public class ExamDaoImpl implements ExamDao {


    private SqlSessionFactory sqlSessionFactory ;

    //后续和spring框架整合之后,就可以保证sqlSessionFactory对象是一个单例对象
    public ExamDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    @Override
    public Exam selectExamById(Integer id) throws Exception {

        //3,打开会话
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //4,执行MappedStatement
        Exam exam = sqlSession.selectOne("selectExamById", id);
        //5,关闭会话
        sqlSession .close();
        return exam;
    }

    @Override
    public int addExam(Exam inputExam) throws Exception {

        //3,打开会话
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //4,执行MappedStatement
        int addExam = sqlSession.insert("addExam", inputExam);
        //5,提交事务
        sqlSession.commit();
        //6,关闭会话
        sqlSession.close();
        return addExam;
    }

    @Override
    public int deleteExamById(Integer id) throws Exception {

        //3,打开会话
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //4,执行MappedStatement
        int deleteExamById = sqlSession.insert("deleteExamById", id);
        //5,提交事务
        sqlSession.commit();
        //6,关闭会话
        sqlSession.close();
        return deleteExamById;
    }

    @Override
    public int updateExamById(Exam inputExam) throws Exception {

        //3,打开会话
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //4,执行MappedStatement
        int updateExamById = sqlSession.insert("updateExamById", inputExam);
        //5,提交事务
        sqlSession.commit();
        //6,关闭会话
        sqlSession.close();
        return updateExamById;
    }
}
  • 存在问题
    • ①mapper映射文件和dao实现子类的耦合度过高
    • ②开发中会有大量的dao实现子类,难以维护

mybatis接口代理开发

  • 概述
    • dao接口 + mapper映射文件
  • 开发步骤
    • ①mapper映射文件要和接口放在同一个目录中
    • ②mapper映射文件要和接口名称一致
    • ③mapper映射文件的namespace和接口的全限定类名一致
    • ④MappedStatement的id和接口的方法名称一致
    • ⑤MappedStatement的parameterType和接口的方法的形参类型一致
    • ⑥MappedStatement的resultType和接口的方法的返回值类型一致
    • ⑦代码测试
  • 代码实现
<?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.atguigu.dao.ExamDao">


    <select id="selectExamById" parameterType="int" resultType="com.atguigu.pojo.Exam">
        select *
        from tb_exam
        where id = #{id}
    </select>


    <!--添加exam-->
    <insert id="addExam" parameterType="com.atguigu.pojo.Exam">
        insert into tb_exam
        values (null, #{name}, #{math}, #{english}, #{chinese})
    </insert>

    <!--删除exam-->
    <delete id="deleteExamById" parameterType="int">
        delete
        from tb_exam
        where id = #{id}
    </delete>

    <!--修改exam-->
    <update id="updateExamById" parameterType="com.atguigu.pojo.Exam">
        update tb_exam
        set name    = #{name},
            math    = #{math},
            english = #{english},
            chinese = #{chinese}
        where id = #{id}
    </update>


</mapper>
public class ExamDaoTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws IOException {
        sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(Resources.getResourceAsStream("SqlMapConfig.xml"));
    }

    @Test
    public void selectExamById() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        ExamDao examDao = sqlSession.getMapper(ExamDao.class);
        Exam exam = examDao.selectExamById(2);
        System.out.println("exam = " + exam);
        sqlSession.close();
    }

    @Test
    public void addExam() {
    }

    @Test
    public void deleteExamById() {
    }

    @Test
    public void updateExamById() {
    }
}

SqlMapperConfig配置文件

  • 概述:
    ①properties:用于mybatis中声明变量
    ②setting:缓存、懒加载、日志实现等等
    ③typeAlias:设置别名
    ④plugins:设置插件
    ⑤environments:事务管理器、数据源
    ⑥mappers:加载mapper映射文件

mybatis内置连接池

  • 概述
    • 在Mybatis中也有连接池技术,但是它采用的是自己的连接池技术。在 Mybatis 的 SqlMapConfig.xml配置文件中,通过来实现Mybatis 中连 接池的配置。
  • 分类
    • JndiDataSourceFactory
    • PooledDataSource
    • UnpooledDataSource

enivronments标签

  • 组成
    • transactionManager
      • JDBC : 有事务管理
      • MANAGED : 无事务管理
    • dataSource
      • POOLED
      • UNPOOLED
  • 代码实现
<environments default="development2">

    <environment id="development">
        <!--事务管理器-->
        <transactionManager type="JDBC"/>

        <!--数据源-->
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mydb1"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </dataSource>

    </environment>

    <environment id="development2">
        <!--事务管理器-->
        <transactionManager type="JDBC"/>

        <!--数据源-->
        <dataSource type="UNPOOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mydb1"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </dataSource>

    </environment>
</environments>

properties标签

  • 概述
    用于声明变量并复用

代码实现

<properties>
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb1"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</properties>
<environments default="development">

    <environment id="development">
        <!--事务管理器-->
        <transactionManager type="JDBC"/>

        <!--数据源-->
        <dataSource type="POOLED">
            <property name="driver" value="${driverClass}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>

    </environment>


</environments>
<properties resource="jdbc.properties"></properties>
<!--整合spring之后弃用-->
<environments default="development">
    <environment id="development">
        <!--事务管理器-->
        <transactionManager type="JDBC"/>

        <!--数据源-->
        <dataSource type="POOLED">
            <property name="driver" value="${driverClass}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

settings标签之log4j

  • 概述
    • 在日常开发过程中,排查问题时难免需要输出MyBatis真正执行的SQL语句、参数、结果等 信息,我们就可用借助log4j的概念来实现执行信息的输出
  • 开发步骤
    • ①引入log4j相关依赖
    • ②引入log4j.xml配置文件
    • ③配置mybatis的日志实现
  • ①引入log4j相关依赖
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

②引入log4j.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <param name="Encoding" value="UTF-8"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m  (%F:%L) \n"/>
        </layout>
    </appender>
    <logger name="java.sql">
        <level value="debug"/>
    </logger>
    <logger name="org.apache.ibatis">
        <level value="info"/>
    </logger>

    <!--开启全局日志打印-->
    <root>
        <level value="debug"/>
        <appender-ref ref="STDOUT"/>
    </root>
</log4j:configuration>

③配置mybatis的日志实现

<properties resource="jdbc.properties"></properties>

settings标签之mapUnderscoreToCamelCase

  • 概述
    • 数据库中,表的字段名称为:a_column;java中,类的属性名称为:aColumn。
    • 如果设置mapUnderscoreToCamelCase=true,a_column字段就会自动输出映射到aColumn。
  • 代码实现
<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

typeAliasees

  • 概述
    • 设置java类型的别名
  • 代码实现
<typeAliases>
    
    <typeAlias type="com.atguigu.pojo.User" alias="user" ></typeAlias>
    <typeAlias type="com.atguigu.pojo.Exam" alias="exam" ></typeAlias>

</typeAliases>
<typeAliases>
    <package name="com.atguigu.pojo"/>
</typeAliases>

mappers标签

  • 概述
    • 加载映射配置文件
  • 代码实现
<!--加载映射配置文件-->
<mappers>
    <!--传统dao开发、接口代理开发-->

    <mapper resource="com/atguigu/dao/ExamDao.xml"/>
    <mapper resource="com/atguigu/dao/UserDao.xml"/>

</mappers>
<!--加载映射配置文件-->
<mappers>
    <!--接口代理开发-->
    <mapper class="com.atguigu.dao.UserDao"></mapper>
    <mapper class="com.atguigu.dao.ExamDao"></mapper>
</mappers>
<mappers>

    <!--接口代理开发-->
    <package name="com.atguigu.dao"/>
</mappers>

核心配置文件之plugins插件

  • 概述
    • MyBatis可以使用第三方的插件对功能进行扩展,分页助手PageHelper是将分页的复杂操作 进行封装,使用简单的方式即可获得分页的相关数据
  • 开发步骤
    • ①引入pagehelper相关依赖
    • ②在SqlMapConfig.xml中配置pagehelper
    • ③定义service接口及其实现子类
      • 编写分页代码
    • ④定义dao接口及其实现子类
    • ⑤代码测试
  • ①引入pagehelper相关依赖
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.1</version>
</dependency>

②在SqlMapConfig.xml中配置pagehelper

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <property name="reasonable" value="true"/>
    </plugin>
</plugins>

③定义service接口及其实现子类

@Override
public PageInfo<Exam> selectExamListByPage(Integer currentPage, Integer pageSize) throws Exception {
    //开启分页查询
    PageHelper.startPage(currentPage, pageSize);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
            .build(Resources.getResourceAsStream("SqlMapConfig.xml"));
    SqlSession sqlSession = sqlSessionFactory.openSession();
    ExamDao examDao = sqlSession.getMapper(ExamDao.class);
    List<Exam> examList = examDao.selectExamList();

    sqlSession.close();
    return new PageInfo<>(examList);
}

**- ④定义dao接口及其实现子类

  • ⑤代码测试**
    @Test
    public void selectExamListByPage() throws Exception {
        ExamService examService = new ExamServiceImpl();
        PageInfo<Exam> pageInfo = examService.selectExamListByPage(2, 2);
        System.out.println("pageInfo = " + pageInfo);
        System.out.println("当前页数:"+pageInfo.getPageNum());
        System.out.println("每页记录数:"+pageInfo.getPageSize());
        System.out.println("总页数:"+pageInfo.getPages());
        System.out.println("上一页的页码:"+pageInfo.getPrePage());
        System.out.println("下一页的页码:"+pageInfo.getNextPage());
        System.out.println("是否是第一页:"+pageInfo.isIsFirstPage());
        System.out.println("是否是最后一页:"+pageInfo.isIsLastPage());
        System.out.println("总记录数:"+pageInfo.getTotal());
        System.out.println("当前页数据:"+pageInfo.getList());
    }

增删改后必须手动提交

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值