Spring framework day 02:Spring 整合 Mybatis

前言

在现代软件开发中,数据持久化是一个重要的环节。为了高效、可维护地管理和操作数据库,许多开发者采用了Spring框架和Mybatis持久化框架的组合。Spring提供了依赖注入和面向切面编程等特性,而Mybatis则是一个优秀的对象关系映射(ORM)框架,能够有效地管理数据库与Java对象之间的转换。

本文将介绍如何使用Spring整合Mybatis来简化数据持久化的过程。首先,我们将简单介绍Spring框架和Mybatis框架的基本概念和原理,接着详细探讨Spring和Mybatis整合的步骤以及如何配置和使用它们。

通过阅读本文,您将了解到Spring整合Mybatis的优势和核心功能,以及如何利用它们来提高开发效率和降低代码的复杂度。无论您是初学者还是有一定经验的开发者,本文都会为您提供实用的指导和最佳实践。

一、为什么要使用 Spring 整合 Mybatis

使用Spring整合Mybatis有以下几个重要原因:

  1. 简化配置和管理:Spring框架提供了依赖注入和控制反转(IoC)的机制,将对象的创建和依赖关系的管理交给Spring容器处理。通过Spring的配置文件,我们可以轻松地配置Mybatis的数据源、事务管理器等,并将Mapper对象注入到Spring容器中。这样一来,我们不再需要手动管理对象的创建和依赖关系,大大简化了配置和管理的工作。

  2. 提供声明式事务管理:Spring框架为数据库事务管理提供了强大的支持。通过Spring整合Mybatis,我们可以使用Spring的事务管理器来管理数据库事务,实现对数据的一致性和完整性的保护。通过声明式的方式,我们可以以简洁、可维护的方式定义事务的边界,而无需手动编写繁琐的事务管理代码。

  3. 实现面向切面编程:Spring框架的另一个重要特性是面向切面编程(AOP)。通过AOP,我们可以在系统的不同层次上进行横切关注点的处理,如日志记录、异常处理、性能监控等。Spring整合Mybatis使得我们可以利用AOP机制来实现对持久层的横切关注点处理,例如对SQL语句的日志记录和缓存管理等,极大地提高了系统的灵活性和可维护性。

  4. 促进代码的模块化和可重用性:通过Spring整合Mybatis,我们可以将数据访问层的逻辑封装在Mapper接口中,并使用Spring的依赖注入将Mapper对象注入到服务层中。这样一来,我们可以更好地实现代码的模块化和组件化,进一步提高代码的可重用性和可测试性。此外,Mybatis本身也提供了很多数据库操作的常用功能,如条件查询、分页查询、动态SQL等,可以让我们更加高效地编写数据访问层的代码。

综上所述,使用Spring整合Mybatis可以简化配置和管理、提供声明式事务管理、实现面向切面编程,同时也促进了代码的模块化和可重用性。这使得开发人员可以更加专注于业务逻辑的实现,提高开发效率和软件质量。

在后面我也会通过一个 spring 整合 Mybatis 的案例来加入事务管理!

二、开始学习

1、新建项目,结构如下
2、添加依赖
XML 复制代码
  <dependencies>
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.15</version>
        </dependency>
 
 
        <!-- spring 的核心依赖 -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.23</version>
        </dependency>
 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.23</version>
        </dependency>
 
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.4.5</version>
        </dependency>
 
 
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
 
 <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>
 
      <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <!-- Mybatis 依赖 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>

 
 
    </dependencies>

这些依赖主要是用于构建一个基于Spring和Mybatis的Java项目,实现与数据库的交互和管理。

  1. com.alibaba:druid:Druid是一种开源的关系型数据库连接池,提供了比传统连接池更强大的功能和性能监控。通过引入这个依赖,我们可以使用Druid来管理数据库连接。

  2. org.springframework:spring-context:Spring框架的核心依赖之一,提供了IoC(控制反转)和DI(依赖注入)等核心功能。通过引入这个依赖,我们可以使用Spring来管理应用程序的组件和依赖关系。

  3. org.springframework:spring-jdbc:Spring框架提供的数据访问层的依赖,包含了与JDBC相关的类和接口。通过引入这个依赖,我们可以使用Spring提供的JDBC支持进行数据库访问和操作。

  4. ch.qos.logback:logback-classic:Logback是一个灵活的日志框架,可以替代传统的Log4j。logback-classic是Logback的经典实现,提供了日志记录的功能。通过引入这个依赖,我们可以使用Logback来记录应用程序的日志。

  5. mysql:mysql-connector-java:MySQL数据库的Java驱动程序,通过引入这个依赖,我们可以连接和操作MySQL数据库。

  6. org.projectlombok:lombok:Lombok是一个Java库,可以通过注解来自动生成代码,减少重复的样板代码。通过引入这个依赖,我们可以简化Java类的定义和编写。

  7. junit:junit:JUnit是一个用于编写单元测试的框架。通过引入这个依赖(scope设置为test),我们可以使用JUnit来编写和运行单元测试。

  8. org.mybatis:mybatis:MyBatis框架的核心依赖,用于数据库访问和映射。详细信息请参考前面的回答。

  9. org.mybatis:mybatis-spring:MyBatis与Spring框架整合的依赖,提供了MyBatis与Spring集成的支持。详细信息请参考前面的回答。

这些依赖一起使用,可以构建一个基于Spring和MyBatis的Java项目,并实现数据库访问和管理的功能。请注意检查版本号,确保使用的版本兼容并与其他相关依赖项一致。

3、创建数据库表

链接: 百度网盘 请输入提取码 提取码: fmq9 复制这段内容后打开百度网盘手机App,操作更方便哦

由于数据量太大了,只能上传到网盘上,大家去拷贝就可以了。

4、在 entity 包下新建一个实体类 City
java 复制代码
@Data
public class City {

    private String cityId;
    private String cityName;
    private String cityCode;
    private String province;

}
5、在 dao 包下新建一个 CityDao 接口
java 复制代码
public interface CityDao {

    /**
     * 根据省份查询
     * @param province
     * @return
     */
    List<City> list(String province);

}

这次演示的案例是,根据条件查询城市信息。

6、在 service 包下新建一个 CityService 接口,在 impl 包下新建一个 CityServiceImpl 实现类

CtiytService 接口

java 复制代码
public interface CityService {

    List<City> listCity(String province);


}

CityServiceImpl 实现类

java 复制代码
@Service
@Slf4j
@RequiredArgsConstructor
public class CityServiceImpl implements CityService {

    /**
     * 这里注入的是代理对象
     */
    private final CityDao cityDao;

    @Override
    public List<City> listCity(String province) {
        return cityDao.list(province);
    }



}

这段代码是一个基于Spring框架的Java类,其中@Service注解表示这个类是一个服务组件,会被Spring容器管理。@Slf4j注解则表示引入了Lombok库,可以使用log对象进行日志记录。

@RequiredArgsConstructor注解是Lombok库提供的注解,它会自动生成一个构造方法,参数为类中已经声明的final成员变量,对于这段代码中的cityDao,它会在构造方法中被赋值。

CityServiceImpl类实现了CityService接口,并覆写了listCity方法。在这个方法中,调用cityDao.list(province)方法获取数据并返回。这个方法实际上是委托给另一个组件CityDao来完成的,因为cityDao是通过构造函数注入进来的。

由于cityDao是一个代理对象,而非CityDao接口原本的实现类,在运行时会动态生成一个代理实现,实现了对CityDao接口的方法调用拦截和增强等功能,以便实现事务管理、缓存等功能。

7、在 resources 包下新建一个db.properties文件,在mappers包下新建一个CityMapper.xml

db.properties 文件

java 复制代码
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/psm
username= root
password = 123456
maxActive = 200
initialSize = 5
minIdle = 5
maxWait = 2000
minEvictableIdleTimeMillis = 300000
timeBetweenEvictionRunsMillis = 60000
testWhileIdle = true
testOnReturn = false
validationQuery = select 1
poolPreparedStatements = false

这些属性是用于配置Druid连接池的相关参数,具体含义如下:

  1. driver:数据库驱动类的全限定名,这里指定使用MySQL数据库的驱动。
  2. url:数据库连接的URL地址,指向本地MySQL数据库。设置了useUnicode=true和characterEncoding=utf-8,表示使用UTF-8字符集编码。
  3. name:连接数据库所需的用户名,这里设置为"root"。注意:这里本来是 username ,为什么要改成 name 呢?因为写 username 的话会识别成本机的用户名,所以这里要改成 name.
  4. password:连接数据库所需的密码,这里设置为"123456"。
  5. maxActive:连接池中同时可从数据源获取的最大活跃连接数,这里设置为200,即同时最多容纳200个连接。
  6. initialSize:初始化时创建的连接数,这里设置为5。
  7. minIdle:连接池中保持的最小空闲连接数,这里设置为5。
  8. maxWait:当连接池没有可用连接时,等待获取连接的最大时间(单位:毫秒),这里设置为2000毫秒。
  9. minEvictableIdleTimeMillis:连接在池中最小空闲时间(单位:毫秒),这里设置为300000毫秒(即5分钟)。
  10. timeBetweenEvictionRunsMillis:间隔多久进行一次空闲连接的检测(单位:毫秒),这里设置为60000毫秒(即1分钟)。
  11. testWhileIdle:在连接空闲时,是否执行validationQuery检测连接是否有效,这里设置为true。
  12. testOnReturn:在归还连接到连接池时,是否执行validationQuery检测连接是否有效,这里设置为false。
  13. validationQuery:用于检测连接是否有效的SQL查询语句,这里设置为"select 1"。
  14. poolPreparedStatements:是否缓存PreparedStatement(预编译的SQL语句),这里设置为false。

通过配置这些属性,可以更好地管理和优化Druid连接池的使用。可以指定数据库连接的URL、用户名和密码,设置连接池的大小、最大活跃连接数、空闲连接数等参数,以及进行连接的有效性校验和空闲连接的检测等。

注意:这些属性不能写错,写错了就不会生效了,会报错。

CityMapper.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">
<mapper namespace="edu.nf.ch02.dao.CityDao">

    <resultMap id="cityMap" type="edu.nf.ch02.entity.City">
        <id property="cityId" column="city_id"/>
        <result property="cityName" column="city_name"/>
        <result property="cityCode" column="city_code"/>
        <result property="province" column="province"/>
    </resultMap>

    <select id="list" parameterType="string" resultMap="cityMap">
        select city_id,city_name,city_code,province
         from city_info where province = #{province}
    </select>


</mapper>

这是一个MyBatis的映射文件(mapper),用于定义数据库操作的SQL语句和结果映射规则。

在这个映射文件中,首先声明了一个命名空间 namespace 为 edu.nf.ch02.dao.CityDao,这个命名空间和Java接口 CityDao 对应。这个接口定义了与数据库交互的方法。

接着定义了一个 resultMap 标签,id 为 cityMap,type 为 edu.nf.ch02.entity.City,表示将查询结果映射到 City 类。在 resultMap 中定义了四个属性映射关系,分别为 cityId、cityName、cityCode 和 province,对应数据库表中的列名。

最后是一个 select 标签,id 为 list,参数类型为 String,结果映射使用了之前定义的 cityMap。SQL语句为 select city_id, city_name, city_code, province from city_info where province = #{province},其中 #{province} 是一个占位符,表示传入的参数值。

通过这个映射文件,MyBatis 就知道如何执行查询操作,并将查询结果映射到 City 类的对象中。这样,在使用 CityDao 接口中的方法时,Mybatis会根据映射文件中的定义来执行相应的SQL语句并返回结果。

8、在 config 包下新建一个 AppConfig 配置类
java 复制代码
@Configuration
// 扫描 dao 接口的包,动态生成 dao 接口的代理实现
// 等效于 xml 中的 <mybatis:scan>
@MapperScan(basePackages = "edu.nf.ch02.dao")
@ComponentScan(basePackages = "edu.nf.ch02")
public class AppConfig {

    /**
     * 装配 dataSource 数据源
     *
     * @return
     * @throws Exception
     */
    @Bean(initMethod = "init", destroyMethod = "close")
    public DruidDataSource dateSource() throws Exception {

        // 创建 Properties 对象
        Properties prop = new Properties();

        // 获取一个输入流来读取 properties 文件
        InputStream input = AppConfig.class.getClassLoader().getResourceAsStream("db.properties");

        // 将输入流加载到 properties 对象中
        prop.load(input);

        // 通过 DruidDataSourceFactory 来创建 DruidDataSource 实例
        DruidDataSource ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(prop);

        return ds;
    }

    /**
     * 整合 mybatis ,装配 SqlSessionFactory
     *
     * @return
     */
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception {
        // 创建 SqlSessionFactoryBean
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        // 注入数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        // 注入 mybatis 其他属性
        // 设置包的别名
        sqlSessionFactoryBean.setTypeAliasesPackage("edu.nf.ch02.entity");
        // mapper 映射配置文件的路径
        // 先创建一个资源路径解析器来查找源文件
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:mappers/*.xml");
        sqlSessionFactoryBean.setMapperLocations(resources);


        // 返回 SqlSessionFactoryBean 给容器
        return sqlSessionFactoryBean;

    }

}

这是一个Spring的配置类 AppConfig,用于配置整合 MyBatis 和数据源。

首先使用注解 @MapperScan 扫描包 edu.nf.ch02.dao 下的接口,动态生成接口的代理实现类。相当于在XML中使用 <mybatis:scan> 配置。

然后使用注解 @ComponentScan 扫描包 edu.nf.ch02,将标有 @Component、@Service、@Repository、@Controller 等注解的类纳入Spring容器管理。

下面定义了一个名为 dataSource 的Bean方法,返回一个 DruidDataSource 实例,该方法通过读取 db.properties 文件中的配置来创建数据源。使用了 @Bean 注解,同时指定了初始化方法 init 和销毁方法 close。

接着定义了一个名为 sqlSessionFactory 的Bean方法,返回一个 SqlSessionFactoryBean 实例。该方法需要传入数据源 dataSource。在方法中,创建了 SqlSessionFactoryBean 对象,并设置了数据源和其他一些属性,比如设置了实体类的别名包路径和映射文件的位置。使用了 @Bean 注解。

这样,在Spring容器启动时,会根据配置生成数据源和SqlSessionFactory,并注册到容器中供其他组件使用。

9、测试
java 复制代码
@Slf4j
public class Main {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 从容器中获取动态创建的 CityDao 的代理对象
        CityService cityDao = context.getBean(CityService.class);
        List<City> list = cityDao.listCity("广东");
        list.forEach(city -> log.info(city.getCityName()));
    }

}

运行结果

在 main 方法中,创建了一个 ApplicationContext 对象,并指定使用 AnnotationConfigApplicationContext 类来加载应用程序配置类 AppConfig。这样就会根据 AppConfig 中的配置信息创建并配置Spring容器。

接下来,通过容器对象 context 的 getBean 方法,传入 CityService.class 参数来获取动态生成的 CityDao 的代理对象。这里假设 CityService 是 CityDao 接口的实现类。

然后,调用 cityDao 的方法 listCity("广东") 查询城市列表,并将结果保存到 list 集合中。

最后,使用 forEach 方法遍历 list 集合中的每个城市对象,并使用日志记录器 log 打印城市名称。

这样,运行程序时,就会通过Spring容器获取CityDao的代理对象,并使用它查询并打印城市列表的名称。

三、总结

以前我们操作数据库是不是没有这么方便,以前我们要写大量的 dao 实现类的代码去操作(CRUD)数据库,现在使用 spring 整合 Mybatis 是不是不用写 dao 实现类了,是不是很方便。大大节省了开发时间和开发效率,使用框架的好处就体现出来了。

这个案例还没有完全讲完,我将在下一篇博客中继续讲解 spring 整合 Mybatis,下一章讲的就是 spring 整合 Mybatis 分页,使用 pagehelper 实现分页功能。

注意:完成这个案例之前建议先去看看我上一篇博客,spring 整合数据源。

四、gitee 案例

完整代码地址:qiuqiu/conformity-study (gitee.com)

相关推荐
霸道流氓气质3 分钟前
AI 聊天机器人组件:ChatMemory 对话记忆、SSE 心跳保活与可嵌入组件封装的 Vue3 + Spring AI 生产级实战
人工智能·spring·机器人
萧瑟余晖17 小时前
Spring Security会话管理与CSRF详解
spring·csrf
Wx-bishekaifayuan17 小时前
springboot铜仁非遗之家76938-计算机课程设计、毕业设计
java·spring boot·后端·spring·django·课程设计·旅游
duxingzhe031118 小时前
我的一些书
java·数据库·tomcat·数据库开发·etl工程师
青春不朽51218 小时前
Python 里 a is b 有时 True 有时 False?小整数缓存和常量折叠的底层真相
python·spring·缓存
苏渡苇18 小时前
Spring Insight:跨服务调用链路是怎么串起来的?
spring boot·后端·spring·系统监控·apm
夕除20 小时前
redis--主从还是集群,内存
java·spring·mybatis
驭渊的小故事20 小时前
MyBatis-Plus 实战指南:从基础 CRUD 到条件构造器与自定义 SQL(二)
数据库·sql·mybatis
Mikko720 小时前
Spring Boot 3.5.16 自带的 Tomcat 10.1.55 中了哪些 CVE?其中一条是修上一个漏洞时带进来的
java·spring boot·后端·安全·tomcat