mybatis和spring整合,xml和注解方式实战

mybatis和spring的整合是mybatis开发团队主动开发一套集成框架,方便与spring整合,包括后面的mybatis与springboot整合!

本章将会以简略的步骤告诉你如何安装和配置 MyBatis-Spring,并构建一个简单的具备事务管理功能的数据访问应用程序。

1、什么是 MyBatis-Spring?

MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。

2、MyBatis-Spring 需要以下版本:

MyBatis-SpringMyBatisSpring FrameworkSpring BatchJava
2.03.5+5.0+4.0+Java 8+
1.33.4+3.2.2+2.1+Java 6+

3、安装依赖

要使用 MyBatis-Spring 模块,只需要在类路径下包含 mybatis-spring-2.0.6.jar 文件和相关依赖即可。

本文采用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可:

   <!-- mybatis 整合 spring 的依赖包 -->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis-spring</artifactId>
          <version>2.0.6</version>
        </dependency>
        <!-- mybatis 依赖包 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <!-- spring jdbc 配置数据源-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
        <!-- 数据库连接池 -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!-- mysql 连接驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>

4、使用XML方式集成spring

集成思想一定要清晰,大致思路如下:

1、将mybatis核心的对象构建起来(首先mybatis需要的东西都要有),目的就是注册进spring的IOC中。

2、分布走,mybatis需要的插件,比如数据库连接等。然后再构建SqlSessionFactory 等。

3、核心注册进去后,mybatis的功能要实现,把xml、接口位置等参数注册进相对于的对象中,比如:扫描的xml位置,扫描的接口包等。

项目的整体代码结构:

图片

1、构建SqlSessionFactory

要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据映射器类。

在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean来创建 SqlSessionFactory。要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中:

 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
   <property name="dataSource" ref="dataSource" />
 </bean>

注意:SqlSessionFactory 需要一个 DataSource(数据源)。这可以是任意的 DataSource,只需要和配置其它 Spring 数据库连接一样配置它就可以了。

2、构建UserInfoMapper 接口

假设你定义了一个如下的 UserInfoMapper 接口:

 public interface UserInfoMapper {
     // 采用注解的方式 编写sql。Map<String, Object>可以修改为UserInfoVO,mybatis自动识别
     // 这种方式,在mybatis的配置文件中只需要引入 该接口即可。
     @Select("select user_code AS userCode, url, user_name AS userName, password FROM user_config WHERE user_code = #{userCode}")
     Map<String, Object> getUserConfig(@Param("userCode") String userCode);
 
 }

那么可以通过 MapperFactoryBean 将接口加入到 Spring 中:

 <!-- 配置 userMapper 接口 -->
    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface" value="com.fagejiang.mapper.UserInfoMapper"/>
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

需要注意的是:所指定的映射器类必须是一个接口,而不是具体的实现类。在这个示例中,通过注解来指定 SQL 语句,但是也可以使用 MyBatis 映射器的 XML 配置文件。

配置好之后,你就可以像 Spring 中普通的 bean 注入方法那样,将映射器注入到你的业务或服务对象中。MapperFactoryBean 将会负责 SqlSession 的创建和关闭。如果使用了 Spring 的事务功能,那么当事务完成时,session 将会被提交或回滚。最终任何异常都会被转换成 Spring 的 DataAccessException 异常。

要调用 MyBatis 的数据方法,只需一行代码:

 @Resource
 UserInfoMapper userInfoMapper;

3、配置事务

一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理。

一旦配置好了 Spring 的事务管理器,你就可以在 Spring 中按你平时的方式来配置事务。并且支持 @Transactional 注解和 AOP 风格的配置。在事务处理期间,一个单独的 SqlSession 对象将会被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。

事务配置好了以后,MyBatis-Spring 将会透明地管理事务。这样在你的 DAO 类中就不需要额外的代码了。

要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象:

 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
   <constructor-arg ref="dataSource" />
 </bean>

4、配置sqlSession

在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession。一旦你获得一个 session 之后,你可以使用它来执行映射了的语句,提交或回滚连接,最后,当不再需要它的时候,你可以关闭 session。使用 MyBatis-Spring 之后,你不再需要直接使用 SqlSessionFactory 了,因为你的 bean 可以被注入一个线程安全的 SqlSession,它能基于 Spring 的事务配置来自动提交、回滚、关闭 session。

SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSessionSqlSessionTemplate 是线程安全的,可以被多个 DAO 或映射器所共享使用。

更多可参考官方文档

可以使用 SqlSessionFactory 作为构造方法的参数来创建 SqlSessionTemplate 对象。

 <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
   <constructor-arg index="0" ref="sqlSessionFactory" />
 </bean>

如果选择使用sqlsession的话,可直接配置接口(借助官方文档上的例子,做参考:)

public class UserDaoImpl implements UserDao {
 
   private SqlSession sqlSession;
 
   public void setSqlSession(SqlSession sqlSession) {
     this.sqlSession = sqlSession;
   }
 
   public User getUser(String userId) {
     return sqlSession.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
   }
 }

按下面这样,注入 SqlSessionTemplate:

 <bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
   <property name="sqlSession" ref="sqlSession" />
 </bean>

5、注入映射器

不需要一个个地注册你的所有映射器。你可以让 MyBatis-Spring 对类路径进行扫描来发现它们。

使用xml的方式来发现映射器:

  • 使用 <mybatis:scan/> 元素

     <mybatis:scan base-package="com.fagejiang.mapper"/>

6、完整的spring.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"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
         https://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
         https://www.springframework.org/schema/context/spring-context.xsd
         http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
 
     <!-- 导入外部的资源文件 -->
     <context:property-placeholder location="classpath:mysql.properties"/>
     <!-- 设置mybatis 别名包 -->
     <mybatis:scan base-package="com.fagejiang.mapper"/>
 
     <!-- 配置数据库连接池:https://blog.csdn.net/lanwp5302/article/details/106461908 -->
     <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
         <!--<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" /> mysql8 -->
         <property name="jdbcUrl" value="${mysql.url}"/>
         <property name="username" value="${mysql.username}"/>
         <property name="password" value="${mysql.password}"/>
         <!-- maximumPoolSize 默认 10 -->
         <property name="maximumPoolSize" value="20"/>
         <!-- minimumIdle 默认 等于 maximumPoolSize -->
         <!--<property name="minimumIdle" value="5"/>-->
         <property name="connectionTestQuery" value="SELECT 1"/>
     </bean>
     <!-- 数据库类型 -->
     <bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
         <property name="properties">
             <props>
                 <prop key="MySQL">mysql</prop>
             </props>
         </property>
     </bean>
     <!-- 配置mybatis 核心的 sqlSessionFactory -->
     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
         <!-- 配置 数据库源 属性 -->
         <property name="dataSource" ref="dataSource"/>
         <!-- 配置扫描的xml路径 -->
         <property name="mapperLocations" value="classpath*:mappers/*.xml"/>
         <!-- 配置数据库类型 -->
         <property name="databaseIdProvider" ref="databaseIdProvider"/>
         <!-- 自 1.3.0 版本开始,新增的 configuration 属性能够在没有对应的 MyBatis XML 配置文件的情况下,直接设置 Configuration 实例。-->
         <property name="configuration">
             <bean class="org.apache.ibatis.session.Configuration">
                 <property name="mapUnderscoreToCamelCase" value="true"/>
             </bean>
         </property>
     </bean>
      <!-- 配置事务管理器 -->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <constructor-arg ref="dataSource"/>
     </bean>
 <!-- 配置 userMapper 接口 -->
     <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
         <property name="mapperInterface" value="com.fagejiang.mapper.UserInfoMapper"/>
         <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
     </bean>
 </beans>

7、测试

1、实体类:

public class UserInfoVO implements Serializable {
     /**
      *
      */
     private static final long serialVersionUID = 2593256431070278531L;
 
     private String userCode;
     private String url;
     private String userName;
     private String password;
     
    ...  省略 setter getter
 }

2、mapper接口

public interface UserInfoMapper {
     // 采用注解的方式 编写sql。Map<String, Object>可以修改为UserInfoVO,mybatis自动识别
     // 这种方式,在mybatis的配置文件中只需要引入 该接口即可。
     @Select("select user_code AS userCode, url, user_name AS userName, password FROM user_config WHERE user_code = #{userCode}")
     Map<String, Object> getUserConfig(@Param("userCode") String userCode);
 
     // 采用 XML的方式编写动态sql,该方式必须在配置文件中引入XML,接口不必引入,
     // XML中的namespace 本身指定的就是接口,mybatis内部自动会处理
     UserInfoVO getUserConfig2(@Param("userCode") String userCode);
 } 

3、数据库

 CREATE TABLE `user_config` (
  `user_code` varchar(30) NOT NULL,
  `url` varchar(200) NOT NULL,
  `user_name` varchar(60) NOT NULL,
  `password` varchar(60) DEFAULT NULL,
  PRIMARY KEY (`user_code`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 INSERT INTO `zswz`.`user_config`(`user_code`, `url`, `user_name`, `password`) VALUES ('test', 'jdbc:mysql://192.168.0.100:13306/zswz', 'root', 'baian2020mql');

数据库配置文件mysql.properties

mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://192.168.0.100:13306/zswz?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&tinyInt1isBit=false&useSSL=false
mysql.username=root
mysql.password=root

4、测试类​​​​​​​

@Slf4j
 public class TestMybatisByXml {
     @Test
     public void testTestMybatisByXml() {
         final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
         final String[] definitionNames = context.getBeanDefinitionNames();
         System.out.println(" definitionNames:");
         Arrays.stream(definitionNames).forEach(System.out::println);
         final UserInfoMapper userMapper = context.getBean("userMapper", UserInfoMapper.class);
         final Map<String, Object> map = userMapper.getUserConfig("test");
         System.out.println("\nmap = " + map);
         final UserInfoVO userInfoVO = userMapper.getUserConfig2("test");
         System.out.println("userInfoVO = " + userInfoVO);
         final UserInfoMapperNoXml infoMapperNoXml = context.getBean("userInfoMapperNoXml", UserInfoMapperNoXml.class);
         final Map<String, Object> test = infoMapperNoXml.getUserConfig("test");
         System.out.println("test = " + test);
    }
 }

运行结果:

图片

5、使用注解的方式

思想和xml一直,故不多bb

1、构建SqlSessionFactory​​​​​​​

/**
      * 配置数据源
      * @return DataSource
      */
     @Bean
     public DataSource dataSource() {
         HikariDataSource dataSource = new HikariDataSource();
         dataSource.setJdbcUrl("jdbc:mysql://192.168.0.100:13306/zswz?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&tinyInt1isBit=false&useSSL=false\n");
         dataSource.setUsername("root");
         dataSource.setPassword("baian2020mql");
         dataSource.setDriverClassName("com.mysql.jdbc.Driver");
         return dataSource;
    }
 
     /**
      * 解析 xml的 工具方法,借钱springboot的mybatis.mapper-locations注入的方法, 源码复制的,寻找源码方法见最下面
      * @return Resource
      */
     public Resource[] resolveMapperLocations() {
         ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
         List<Resource> resources = new ArrayList<Resource>();
         Resource[] mappers = new Resource[0];
         try {
             mappers = resourceResolver.getResources("mappers/*.xml");
        } catch (IOException e) {
             e.printStackTrace();
        }
         resources.addAll(Arrays.asList(mappers));
         return resources.toArray(new Resource[resources.size()]);
    }
 
     /**
      * 配置 SqlSessionFactory ,注入 数据源,映射的xml等信息
      * @return
      * @throws Exception
      */
     @Bean
     public SqlSessionFactory sqlSessionFactory() throws Exception {
         SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
         factoryBean.setDataSource(dataSource());
         factoryBean.setMapperLocations(resolveMapperLocations());
         Properties properties = new Properties();
         properties.setProperty("MySQL", "mysql");
         final VendorDatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
         databaseIdProvider.setProperties(properties);
         factoryBean.setDatabaseIdProvider(databaseIdProvider);
         return factoryBean.getObject();
    }

​​​​​​​2、构建UserInfoMapper 接口​​​​​​​

 @MapperScan(basePackages = "com.fagejiang.mapper")
 public class MybatisConfig {}

3、配置事务​​​​​​​

     @Bean
     public DataSourceTransactionManager transactionManager() {
         return new DataSourceTransactionManager(dataSource());
    } 

4、配置sqlSession​​​​​​​

     @Bean
     public SqlSessionTemplate sqlSession() throws Exception {
         return new SqlSessionTemplate(sqlSessionFactory(), ExecutorType.BATCH);
    }

5、注入映射器

见 SqlSessionFactory 方法

6、spring启动类​​​​​​​

 @Configuration
 @ComponentScan(basePackages="com.fagejiang.config")
 public class SpringAnnotationConfig {
 
 }

7、测试​​​​​​​

public class TestMybatisByAnnotation {
 
     @Test
     public void testAnnotation() {
         final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringAnnotationConfig.class);
         final UserInfoMapper userInfoMapper = context.getBean("userInfoMapper", UserInfoMapper.class);
         final Map<String, Object> map = userInfoMapper.getUserConfig("test");
         System.out.println("\nmap = " + map);
         final UserInfoVO userInfoVO = userInfoMapper.getUserConfig2("test");
         System.out.println("userInfoVO = " + userInfoVO);
         final UserInfoMapperNoXml infoMapperNoXml = context.getBean("userInfoMapperNoXml", UserInfoMapperNoXml.class);
         final Map<String, Object> test = infoMapperNoXml.getUserConfig("test");
         System.out.println("test = " + test);
    }
 }

测试结果:

扩展

找寻源码方法的过程,也是大家学习的可借鉴的一种思路哦:

图片

得到注册到的位置

图片

找到该类被哪里使用了

图片

寻找对应的参数位置

寻找方法

希望大家可以拥有敢于看源码的心,特别是经常使用的框架,例如:mybaits、spring、springboot。了解它的基本流程,属于一定的源码。不管是工作还是以后的面试都是有益的!奥利给

关注公众号,点击关于我,加入QQ群,私聊群主可以联系到我哦,群文件有Java面试以及框架如何使用pdf等免费资源!!!

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

航迹者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值