• Spring5应用之整合MyBatis


    作者简介:☕️大家好,我是Aomsir,一个爱折腾的开发者!
    个人主页Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客
    当前专栏Spring5应用专栏_Aomsir的博客-CSDN博客

    参考文献

    前言

    在我们之前的系列文章中,我们已经深入探讨了Spring5的两大核心组件:IOC和AOP,它们是Spring框架的基石。现在,我们即将开启一个新的篇章,那就是探索Spring5如何与各种持久层技术完美融合

    持久层,顾名思义,是关于数据存储和管理的,它是应用程序中最为关键的部分之一。那么,为什么我们需要将Spring与持久层技术整合呢?首先,整合可以为我们提供一种统一的数据访问策略,使得数据的存储和检索变得更为简洁、高效。其次,通过整合,我们可以充分利用Spring的事务管理、依赖注入等特性,从而使数据操作更加安全和高效。

    Spring5为我们提供了与多种持久层技术的整合支持,包括但不限于Hibernate(JPA)JDBCMyBatis等。在这几节课中,我们将特别关注于如何与当前非常主流的MyBatis框架进行整合。MyBatis是一个优秀的持久层ORM框架,它提供了简洁、灵活的SQL映射和数据访问策略。

    那么,跟我一起,逐步揭开Spring与持久层整合的神秘面纱,通过实战和案例,体验其带来的便利与强大功能!

    为什么要整合持久层?

    1. 企业级应用的需求:在JavaEE的开发中,数据存储和管理是不可或缺的部分,尤其当涉及到大量的用户信息、交易记录、商品数据等。为了确保数据的一致性、安全性和高效性,我们需要一种可靠的方法来访问和操作数据库,这就是持久层的职责。
    2. 解决代码冗余的问题:虽然原生的JDBC、Hibernate和MyBatis为我们提供了进行持久化开发的基础,但在实际的开发过程中,我们经常会遇到大量的重复代码,如连接管理、异常处理等。这不仅使得代码难以维护,而且增加了出错的可能性。
    3. Spring的高效封装:Spring框架,凭借其模板设计模式,对各种持久层技术提供了一层进一步的封装。例如,JdbcTemplate为JDBC提供了更为简洁、高效的操作方式;而HibernateTemplate则为Hibernate提供了更为丰富的功能支持。这些封装不仅简化了代码,还提高了开发的效率和质量。

    综上所述,整合持久层不仅是为了满足JavaEE开发的基本需求,更是为了提高开发的效率、减少错误和提升应用的可维护性。通过与Spring的整合,我们可以充分发挥两者的优势,为企业级应用带来更为稳定、高效的数据管理解决方案

    能与哪些持久层技术整合?

    1. JDBC:Java数据库连接(JDBC)是Java中用于连接数据库的标准API。然而,原生的JDBC开发需要编写大量模板代码,如建立连接、释放资源等。为了简化这一过程,Spring为我们提供了JDBCTemplate。通过使用JDBCTemplate,开发者可以更为轻松地执行查询、更新等操作,而无需担心常见的资源泄漏或异常处理问题。
    2. Hibernate (JPA)Hibernate是一个流行的ORM(对象关系映射)框架,而JPA(Java持久化API)是Java平台上的一个规范,Hibernate是JPA的一种实现。Spring为Hibernate提供了HibernateTemplate工具,它可以简化许多常见的Hibernate操作,并且为我们处理事务、会话等常见问题。使用Spring与Hibernate的整合,开发者可以轻松地将数据库记录映射到Java对象,并执行持久化操作。
    3. MyBatisMyBatis是另一个流行的持久层框架,它允许开发者直接编写SQL,同时提供了灵活的结果映射功能。Spring为MyBatis提供了一系列工具,如SqlSessionFactoryBeanMapperScannerConfigurer,这些工具旨在简化MyBatis配置和使用过程。通过整合,开发者可以在Spring应用中方便地使用MyBatis的特性,同时享受Spring提供的事务管理、依赖注入等功能。

    总的来说,无论开发者选择哪种持久层技术,Spring都为其提供了一套完备的解决方案,这些方案旨在简化开发过程、增加生产效率,并确保应用的健壮性和可维护性

    MyBatis整合

    编码七步骤回顾

    MyBatis原生的开发一共有如下几个步骤

    • 实体
    • 实体别名
    • 数据表
    • 创建DAO接口
    • 实现Mapper文件
    • 注册Mapper文件
    • MyBatisAPI的调用

    开发步骤

    • 引入依赖(暂时不需要Spring相关依赖)
    • 创建数据库表(user)
    • 创建数据表对应的实体类(User.java)
    • 创建DAO接口(UserDAO.java)
    • 创建DAO接口对应的Mapper文件(UserMapper.xml)
    • MyBatis全局配置文件中配置别名与注册文件(mybatis-config.xml)
    • 编写测试使用MyBatisAPI进行调用
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>8.0.31version>
    dependency>
    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatisartifactId>
        <version>3.4.6version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    # 演示所用user数据表
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for user
    -- ----------------------------
    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user` (
      `id` int NOT NULL AUTO_INCREMENT,
      `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
      `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    /**
     * 数据表user对应的实体类
     */
    @Data
    public class User implements Serializable {
        private Integer id;
        private String name;
        private String password;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    public interface UserDAO {
        void save(User user);
    }
    
    • 1
    • 2
    • 3
    <mapper namespace="com.aomsir.basic.mybatis.dao.UserDAO">
        <insert id="save" parameterType="user">
            INSERT INTO user(id, name, password)
            VALUES (#{id}, #{name}, #{password})
        insert>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <typeAliases>
            
            <typeAlias type="com.aomsir.basic.mybatis.entity.User" alias="user"/>
        typeAliases>
    
        
        <environments default="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC" />
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3307/suns_mybatis?useSSL=false"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                dataSource>
            environment>
        environments>
    
        
        <mappers>
            <mapper resource="mapper/UserMapper.xml"/>
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    public class TestMybatis {
        @Test
        public void test1() throws IOException {
            // 1.读取配置文件创建SqlSessionFactory对象
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2.获取SqlSession对象并获取到DAO接口的代理对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            UserDAO userDAO = sqlSession.getMapper(UserDAO.class);
    
            User user = new User();
            user.setName("Aomsir");
            user.setPassword("123456");
    
            // 3.调用DAO接口的方法执行数据库操作
            userDAO.save(user);
            
            // 4.提交事务
            sqlSession.commit();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述
    在这里插入图片描述

    原生MyBatis存在的问题

    1. 配置繁琐
      • 实体别名注册:在MyBatis中,为每个实体类定义别名可以使XML映射文件中的代码更加简洁。但当有大量实体类时,手动为每一个实体类设置别名会非常繁琐。
      • Mapper文件注册:在配置MyBatis时,我们需要为每个Mapper XML文件进行注册,这使得配置文件变得冗长,难以管理。
      • 包扫描:虽然现代版本的MyBatis提供了package属性来自动扫描别名,但在之前的版本中这是不支持的,增加了使用的复杂性。
    2. 代码冗余
      • API调用:在使用MyBatis API进行数据库操作时,我们往往需要执行多个步骤,包括获取SqlSession、执行操作、处理异常和关闭SqlSession等。这些操作在每次数据库访问时都需要重复,导致代码冗余。
      • 资源管理:虽然MyBatis为我们提供了资源的自动管理,但在某些情况下,开发者仍需要手动管理数据库连接、会话等资源,这增加了开发的复杂性。
      • 异常处理:在使用MyBatis进行数据库操作时,可能会抛出多种异常。处理这些异常需要额外的代码,使得主逻辑变得不那么清晰。

    整合思路分析

    对于许多Java开发者来说,MyBatis与Spring的整合可以说是如虎添翼,使得持久层的开发更为简洁、高效。那么,如何在Spring中优雅地整合MyBatis呢?以下是从MyBatis API调用角度进行的一步步分析:

    1. SqlSessionFactoryBean的引入
      在原生MyBatis开发中,我们需要手动读取配置文件来创建SqlSessionFactory对象,这个过程既繁琐又容易出错。Spring为我们提供了SqlSessionFactoryBean来优化这个过程。这个Bean负责读取MyBatis的配置信息,如类型别名、数据源及Mapper文件的注册信息等,并为我们自动创建SqlSessionFactory。这意味着,原来分散在MyBatis配置文件中的大量配置信息,现在都可以集中管理在Spring的配置文件中,使配置更为集中和统一。而mybatis-config.xml配置文件,成为了一个可选的配置,只有在有特殊配置需求时才需要。温馨提示:对于FactoryBean的概念,如果你还不是很熟悉,可以回顾我之前的文章《Spring5应用之复杂对象》来进行复习。

    2. MapperScannerConfigurer的应用
      在原生MyBatis开发中,要获取DAO接口的代理对象往往需要手动编写一些代码。而在Spring中,为了进一步简化这个过程,Spring为我们提供了MapperScannerConfigurer。这个组件负责自动扫描指定包下的MyBatis的DAO接口,并为每一个接口自动创建代理对象。它需要知道SqlSessionFactory以及DAO接口所在的目录,一旦配置完毕,开发者可以轻松地在Spring容器中获得DAO接口的代理对象,无需再手动创建。

    总的来说,Spring为我们提供的这些组件,都是为了简化和优化原生MyBatis的开发过程。通过使用它们,我们可以更高效地进行持久层的开发,同时也能享受到Spring为我们带来的其他优势,如事务管理、依赖注入等。
    在这里插入图片描述

    整合编码开发步骤

    • 引入依赖
    • Spring配置文件进行相关配置
    • 编码调用
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-jdbcartifactId>
        <version>5.1.14.RELEASEversion>
    dependency>
    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatis-springartifactId>
        <version>2.0.2version>
    dependency>
    
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druidartifactId>
        <version>1.1.18version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3307/suns_mybatis?useSSL=false"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        bean>
    
        
        <bean id="ssfb" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="typeAliasesPackage" value="com.aomsir.basic.mybatis.entity"/>
            <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        bean>
    
        
        <bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="sqlSessionFactoryBeanName" value="ssfb"/>
            <property name="basePackage" value="com.aomsir.basic.mybatis.dao"/>
        bean>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    public class TestMybatis {
        /**
         *
         */
        @Test
        public void test2() throws IOException {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext3.xml");
    
            UserDAO userDAO = ctx.getBean(UserDAO.class);
    
            User user = new User();
            user.setName("Aomsir");
            user.setPassword("123456");
    
            userDAO.save(user);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    整合细节分析

    通过对比MyBatis原生开发和Spring整合MyBatis的两种实践,我们观察到在原生MyBatis开发中,每次操作后我们都需要手动提交事务,而在整合了Spring之后,这一步骤变得不再必要。这其中的原因是什么呢?

    其核心在于事务的自动提交属性autoCommit。在原生MyBatis开发中,我们通常使用其提供的默认连接池。当这个连接池创建Connection对象时,它会默认将autoCommit属性设置为false。这意味着我们需要手动控制事务的提交。

    但当我们与Spring整合使用时,往往选择更加强大和灵活的连接池,如Druid。Druid在创建Connection对象时,默认将autoCommit属性设置为true。这使得数据库操作后事务会自动提交,从而省去了我们手动提交事务的步骤

    总结

    在本篇文章中,我们深入探讨了原生MyBatis开发与Spring整合MyBatis开发的各个环节。逐步解构了整合过程中的关键步骤,明晰了整合背后的逻辑和原理。通过透彻的分析,揭示了MyBatis和Spring结合的强大之处,如何使得数据库操作更为流畅、简洁。
    每一步的整合都是为了优化开发流程,减少代码冗余,提高系统的稳定性和效率。特别是对事务的处理,从手动到自动,背后所涉及的知识点都为大家提供了深入思考的空间。

    随着分析的深入,原生的MyBatis和经过Spring整合后的MyBatis展现出了明显的差异,让我们更加认识到框架整合的重要性和必要性。希望本篇文章能为大家带来新的启示,使得在实际开发中更为得心应手,更加得心应手

  • 相关阅读:
    Academic Inquiry|创新与城市间知识溢出:社会、地理和技术的连通性和心理开放性
    大数据技术之HBase+Redis详解
    Linux文件编程(lseek函数和stat函数)
    SQL Server 卸载和安装
    基于Java毕业设计游泳馆管理平台源码+系统+mysql+lw文档+部署软件
    【Python自然语言处理】文本向量化处理用户对不同类型服装评论问题(超详细 附源码)
    【Linux】基础IO
    SAP MM 关于事务代码VL04的一个测试 II
    FFmpeg开发笔记(二十二)FFmpeg中SAR与DAR的显示宽高比
    C#禁用或启用任务管理器
  • 原文地址:https://blog.csdn.net/qq_43266723/article/details/133714549