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语句和结果映射规则。

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

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

最后是一个 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容器。

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

然后,调用 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)

相关推荐
程序猿进阶23 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
xlsw_8 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭10 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
李小白6610 小时前
Spring MVC(上)
java·spring·mvc
Lojarro13 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
zjw_rp13 小时前
Spring-AOP
java·后端·spring·spring-aop
cmdch201716 小时前
Mybatis加密解密查询操作(sql前),where要传入加密后的字段时遇到的问题
数据库·sql·mybatis
撒呼呼16 小时前
# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)
数据库·spring boot·spring·mvc·springboot
天使day17 小时前
SpringMVC
java·spring·java-ee