Spring5应用之整合MyBatis

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

参考文献

前言

在我们之前的系列文章中,我们已经深入探讨了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进行调用
xml 复制代码
<!--MyBatis相关依赖-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.31</version>
</dependency>

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
sql 复制代码
# 演示所用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;
java 复制代码
/**
 * 数据表user对应的实体类
 */
@Data
public class User implements Serializable {
    private Integer id;
    private String name;
    private String password;
}
java 复制代码
public interface UserDAO {
    void save(User user);
}
xml 复制代码
<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>
xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!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>

    <!--Mapper文件注册-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>
java 复制代码
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();
    }
}

原生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配置文件进行相关配置
  • 编码调用
xml 复制代码
<!--Spring整合MyBatis额外需要的依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.1.14.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.2</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.18</version>
</dependency>
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<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>

    <!--SqlSessionFactory-->
    <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>

    <!--Mappe-->
    <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>
java 复制代码
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);
    }
}

整合细节分析

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

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

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

总结

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

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

相关推荐
HUGu RGIN7 小时前
MySQL--》如何在MySQL中打造高效优化索引
android·mysql·adb
callJJ10 小时前
Spring Data Redis 两种编程模型详解:同步 vs 响应式
java·spring boot·redis·python·spring
phltxy10 小时前
Spring Cloud 分布式服务部署实战:从 0 到 1 实现微服务上线
spring·spring cloud·微服务
xmjd msup13 小时前
spring security 超详细使用教程(接入springboot、前后端分离)
java·spring boot·spring
DevilSeagull14 小时前
MySQL(2) 客户端工具和建库
开发语言·数据库·后端·mysql·服务
远洪15 小时前
claude code 国内安装使用
数据库·mysql
myrh pdmd15 小时前
maven导入spring框架
数据库·spring·maven
Nicander15 小时前
理解 mybatis 源码:vibe-coding一个mini-mybatis
后端·mybatis
wangbing112517 小时前
MySQL 官方 GPG 密钥过期问题
数据库·mysql
重生之我是Java开发战士17 小时前
【MySQL】事务 & 用户与权限管理
android·数据库·mysql