Spring-Spring整合MyBatis详解

Spring-Spring整合MyBatis详解概述项目结构配置 SQLMapClient 在 Spring 中配置 MyBatis 编写 Mybatis 的 DAO 使用 SqlSessionTe 使用映射接口源码概述使用 Mybatis 提供的 ORM 机制 面对具体的数据操作 Mybatis 要求开发者编程具体的 SQL 语句 相对于 Hibernate 等全自动的 ORM 机制而言 Mybatis 在开发的工作量和数据库移植性上做出了让步 为数据持久化操作提

概述

使用Mybatis提供的ORM机制,面对具体的数据操作,Mybatis要求开发者编程具体的SQL语句。 相对于Hibernate等全自动的ORM机制而言,Mybatis在开发的工作量和数据库移植性上做出了让步,为数据持久化操作提供了更大的自由空间。

Mybatis的事务管理可以由Spring标准机制进行处理,它和Spring JDBC事务管理的方式完全一致,采用和SpringJDBC相同的DataSourceTransactionManager事务管理器。


项目结构

这里写图片描述


配置SQLMapClient

每个Mybatis的应用程序都以一个SqlSessionFactory对象的实例为核心。
SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象来获得。 SqlSessionFactoryBuilder对象可以从XML配置文件或者Configuration类的实例中构建SqlSessionFactory对象。

和Hibernate相似,Mybatis拥有多个SQL映射文件,并通过一个配置文件对这些SQL映射文件进行装配,同时在该文件中定义一些控制属性的信息。

我们来看一个简单的Mybatis配置文件

myBatisConfig.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <!-- (1) 提供可控制Mybatis框架运行行为的属性信息 --> <setting name="lazyLoadingEnabled" value="false" /> </settings> <typeAliases> <!-- (2) 定义全限定类名的别名,在映射文件中可以通过别名代替具体的类名 --> <typeAlias alias="Artisan" type="com.artisan.domain.Artisan" /> </typeAliases> </configuration> 

在(1)处提供提供可控制Mybatis框架运行行为的属性信息 ,在(2)处定义全限定类名的别名,在映射文件中可以通过别名代替具体的类名,简化配置。

当然我们也可以定义mappers标签引用SQL映射文件,如果我们在MyBatis的总装配置文件myBatisConfig.xml中指定SQL映射文件,则必须逐个列出所有的SQL映射文件,比较繁琐。我们更倾向于 通过SqlSessionFactoryBean提供的mapperLocations属性文件,通过扫描式加载SQL映射文件。 (下文描述)

我们来看下SQL映射文件的内容:

<?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"> <!-- (1)指定命名空间 --> <mapper namespace="com.artisan.dao.mybatis.ArtisanMybatisDao"> <insert id="addArtisan" parameterType="Artisan"> INSERT INTO littel_artisan(artisan_id,artisan_name,artisan_desc) VALUES(#{artisanId},#{artisanName}, #{artisanDesc}) </insert> <select id="selectArtisan" resultType="Artisan" parameterType="String"> select artisan_id artisanId, artisan_name artisanName, artisan_desc artisanDesc from little_artisan where artisan_name = #{artisanName} </select> </mapper> 

该配置文件定义了Artisan实体类机型数据操作时所需要的SQL,同事还定义了查询结果和对象属性的映射关系。(这里我们仅仅列出一个查询示例)。

在(1)指定命名空间,每个具体的映射项都有一个id,可以通过命名空间和映射项的id定位到具体的映射项。

  • 映射项的parameterType指定传入的参数对象,可以是全限定名的二类,也可以是类的别名(别名在Mybatis的主配置文件中定义)比如 <typeAlias alias="Artisan" type="com.artisan.domain.Artisan" />
  • 如果映射项的入参是基础类型或者String类型,则可以通过使用int 、long、String的基础类型名。
  • 如果映射项拥有返回类型对象,通过resultType指定。
  • 在映射项中通过#{XXX}绑定parameterType指定参数类的属性,支持级联属性,比如{anotherDomain.anotherProperty}

在Spring中配置MyBatis

我们使用Mybatis提供的mybatis-spring整合类包实现Spring和Mybatis的整合。 我们添加将mybatis-spring构建pom.xml。

<!-- mybatis ORM框架 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${ 
      mybatis.version}</version> </dependency> <!-- mybatis-spring适配器 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${ 
      mybatis-spring.version}</version> </dependency> 

我们来看下Spring配置Mybatis的配置文件 applicationContext-mybatis.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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 --> <context:component-scan base-package="com.artisan" resource-pattern="/mybatis/*.class"/> <!-- spring里使用org.mybatis.spring.mapper.MapperScannerConfigurer 进行自动扫描的时候,设置了sqlSessionFactory 的话,可能会导致PropertyPlaceholderConfigurer失效,也就是用${jdbc.username}这样之类的表达式,将无法获取到properties文件里的内容。 导致这一原因是因为,MapperScannerConigurer实际是在解析加载bean定义阶段的,这个时候要是设置sqlSessionFactory的话,会导致提前初始化一些类, 这个时候PropertyPlaceholderConfigurer还没来得及替换定义中的变量,导致把表达式当作字符串复制了。 但如果不设置sqlSessionFactory 属性的话,就必须要保证sessionFactory在spring中名称一定要是sqlSessionFactory,否则就无法自动注入。 解决思路: 主要改动了MapperScannerConfigurer的配置,使用sqlSessionFactoryBeanName进行延迟注入 --> <!-- 如果Spring和Mybatis整合,要想使用context:property-placeholder. MapperScannerConfigurer中 p:sqlSessionFactoryBeanName="sqlSessionFactory" 这样配置--> <context:property-placeholder location="classpath:spring/jdbc.properties"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" /> <!-- 通过Spring风格构建Mybatis的SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="dataSource" p:configLocation="classpath:mybatis/myBatisConfig.xml" p:mapperLocations="classpath:com/artisan/domain/mybatis/*.xml"/> <!-- 创建Mybatis访问数据库的模板类 --> <bean class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg ref="sqlSessionFactory"/> </bean> <!-- 查 找 类 路 径 下 的 映 射 器 并 自 动 将 它 们 创 建 成 MapperFactoryBean --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" p:sqlSessionFactoryBeanName="sqlSessionFactory" p:basePackage="com.artisan.dao.mybatis"/> <!-- 暂未用到事务 --> <!-- Spring的事务管理器 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/>--> <!-- 开启事务注解 <tx:annotation-driven transaction-manager="transactionManager"/>--> </beans> 

mybatis-spring类包提供了一个SqlSessionFactoryBean,以便通过Spring风格创建Mybatis的SqlSessionFactory。只需要注入数据源并指定Mybatis的总装配置文件那就可以啦。

我们通过 p:mapperLocations=”classpath:com/artisan/domain/mybatis/*.xml ,SqlSessionFactoryBean将扫描com/artisan/domain/mybatis类路径并加载所有以.xml为后缀的映射文件。


编写Mybatis的DAO

使用SqlSessionTemplate

mybatis-spring效仿Spring的风格提供了一个模板类SQLSessionTemplate,可以通过模板轻松的访问数据库。

首先在applicationContext-mybatis.xml中配置SQLSessionTemplate

 <!-- 创建Mybatis访问数据库的模板类 --> <bean class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg ref="sqlSessionFactory"/> </bean> 

然后就可以通过SqlSessionTemplate调用SQL映射项完成数据访问操作

使用映射接口

Mybatis提供了一种可将SQL映射文件中的映射项通过名称匹配接口进行调用的方法: 接口名称和映射名空间相同,接口方法和映射元素的id相同。

我们在Artisan.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"> <!-- (1)指定命名空间 --> <mapper namespace="com.artisan.dao.mybatis.ArtisanMybatisDao"> <select id="selectArtisan" resultType="Artisan" parameterType="String"> select artisan_id artisanId, artisan_name artisanName, artisan_desc artisanDesc from little_artisan where artisan_name = #{artisanName} </select> </mapper> 

定义同名接口

package com.artisan.dao.mybatis; import com.artisan.domain.Artisan; public interface ArtisanMybatisDao { 
         Artisan selectArtisan(String artisanName); } 

接口名为com.artisan.dao.mybatis.ArtisanMybatisDao,Artisan.xml文件中的每个映射项对应一个接口方法,接口方法的嗯签名和映射项的声明匹配。


查询数据

package com.artisan.dao.mybatis; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.artisan.domain.Artisan; / * * * @ClassName: ArtisanMybatisDaoImpl * * @Description: @Repository标注的DAO层,被Spring管理 * * @author: Mr.Yang * * @date: 2017年10月1日 下午12:18:25 */ @Repository public class ArtisanMybatisDaoImpl implements ArtisanMybatisDao { 
          private SqlSessionTemplate sqlSessionTemplate; // 注入SqlSessionTemplate @Autowired public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { 
          this.sqlSessionTemplate = sqlSessionTemplate; } @Override public Artisan selectArtisan(String artisanName) { 
          // 必须是获取接口 ArtisanMybatisDao artisanMybatisDao = sqlSessionTemplate .getMapper(ArtisanMybatisDao.class); return artisanMybatisDao.selectArtisan(artisanName); } } 

单元测试

package com.artisan.dao.mybatis; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.artisan.domain.Artisan; public class ArtisanMybatisDaoImplTest { 
           ClassPathXmlApplicationContext ctx = null; ArtisanMybatisDaoImpl artisanMybatisDaoImpl = null; @Before public void initContext() { 
           ctx = new ClassPathXmlApplicationContext( "spring/applicationContext-mybatis.xml"); artisanMybatisDaoImpl = ctx.getBean("artisanMybatisDaoImpl", ArtisanMybatisDaoImpl.class); } @Test public void testSelectArtisanWithMybatis() { 
           Artisan artisan = artisanMybatisDaoImpl.selectArtisan("artisan"); System.out.println("Artisan Id:" + artisan.getArtisanId()); System.out.println("Artisan Name:" + artisan.getArtisanName()); System.out.println("Artisan Desc:" + artisan.getArtisanDesc()); } @After public void releaseContext() { 
           if (ctx != null) { 
           ctx.close(); } } } 

输出结果

十月 01, 2017 1:03:30 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@604b7b51: startup date [Sun Oct 01 13:03:30 BOT 2017]; root of context hierarchy 十月 01, 2017 1:03:31 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring/applicationContext-mybatis.xml] DEBUG LogFactory - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. DEBUG SqlSessionFactoryBean - Parsed configuration file: 'class path resource [mybatis/myBatisConfig.xml]' DEBUG SqlSessionFactoryBean - Parsed mapper file: 'file [D:\workspace\workspace-sts\SpringMyBaitsDemo\target\classes\com\artisan\domain\mybatis\Artisan.xml]' DEBUG SqlSessionUtils - Creating a new SqlSession DEBUG SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@558cdd] was not registered for synchronization because synchronization is not active DEBUG SpringManagedTransaction - JDBC Connection [jdbc:oracle:thin:@172.25.246.11:1521:testbed, UserName=CC, Oracle JDBC driver] will not be managed by Spring DEBUG selectArtisan - ==> Preparing: select artisan_id artisanId, artisan_name artisanName, artisan_desc artisanDesc from little_artisan where artisan_name = ? DEBUG selectArtisan - ==> Parameters: artisan(String) DEBUG selectArtisan - <== Total: 1 DEBUG SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@558cdd] Artisan Id:AAAYbEAAZAAAK9fAAA Artisan Name:artisan Artisan Desc:Spring+MyBatis Demo 十月 01, 2017 1:03:36 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@604b7b51: startup date [Sun Oct 01 13:03:30 BOT 2017]; root of context hierarchy 

至此就完成了Spring+Mybatis的整合


Code

源码已托管到Github:https://github.com/yangshangwei/SpringMyBaitsDemo

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233162.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 三层架构(我的理解及具体分析)

    三层架构(我的理解及具体分析)

    2021年11月23日
    40
  • 优化算法——模拟退火算法

    优化算法——模拟退火算法模拟退火算法原理模拟退火算法模拟退火算法过程模拟退火算法流程模拟退火算法的Java实现Java代码最后的结果模拟退火算法原理爬山法是一种贪婪的方法,对于一个优化问题,其大致图像(图像地址)如下图所示:其目标是要找到函数的最大值,若初始化时,初始点的位置在CC处,则会寻找到附近的局部最大值AA点处,由于AA点出是一个局部最大值点,故对于爬山法来讲,该算法无法跳出局部最大值点。若初始

    2022年7月18日
    18
  • linux find命令详解_mount命令详解

    linux find命令详解_mount命令详解find命令格式:findpath-option[-print][-exec-okcommand]{}\;find命令的参数:path:要查找的目录路径。~表示$HO

    2022年8月6日
    6
  • 遗传算法经典实例matlab代码_退火算法与遗传算法

    遗传算法经典实例matlab代码_退火算法与遗传算法经典遗传算法及简单实例(MATLAB)1.遗传算法简单介绍1.1理论基础1.2算法要点1.1编码1.2适应度函数1.3基本流程2.雪兔实例1.遗传算法简单介绍1.1理论基础整个算法的基础就是达尔文的生物进化论,“物竞天择,适者生存”这句话已经是常识了。雪兔的故事:东北那旮瘩,有群原始雪兔,刚从未知物种进化而来,五颜六色(表现型)漂亮极了,称之为I(0)。(注意:种群初始化)入夏了,雪兔们出来觅食,浅色兔在草地中无所遁形,被雪狐收割了一波(大批浅色+小批深色)。入冬了,雪

    2025年11月10日
    2
  • 画二元函数图像_二元函数怎么画图

    画二元函数图像_二元函数怎么画图目录概述字符串表达式解析图像绘制函数作为属性赋值参考以及说明概述本篇博客主要是在上一篇《每个人都该懂点函数式编程》的基础上,进一步说明“函数”在函数式编程中的重要作用。强调了函数和普通类型一样,可以赋

    2022年8月6日
    9
  • C++中this指针的本质

    C++中this指针的本质一直以来对C++中的this不理解,只知道在构造函数中,如果构造函数的参数和类成员的名字一样的话,就可以用this指针来区分,如:this->a=a;一直以来都有这个疑问:this究竟是什么?我们明明没有定义这个this,但是我们可以直接用而编译器不会报错。今天来解决这个疑问。从刚才的代码中,我们用”this->”而不是”this.”就说明this是一个指针,而我们知道,在C、C++中,指针

    2022年5月16日
    46

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号