Mybatis整合Spring

Stella981
• 阅读 672

Mybatis****整合Spring

        根据官方的说法,在ibatis3,也就是Mybatis3问世之前,Spring3的开发工作就已经完成了,所以Spring3中还是没有对 Mybatis3的支持。因此由Mybatis社区自己开发了一个Mybatis-Spring用来满足Mybatis用户整合Spring的需求。下面 就将通过Mybatis-Spring来整合Mybatis跟Spring的用法做一个简单的介绍。

MapperFactoryBean

        首先,我们需要从Mybatis官网上下载Mybatis-Spring的jar包添加到我们项目的类路径下,当然也需要添加Mybatis的相关jar 包和Spring的相关jar包。我们知道在Mybatis的所有操作都是基于一个SqlSession的,而SqlSession是由 SqlSessionFactory来产生的,SqlSessionFactory又是由SqlSessionFactoryBuilder来生成的。但 是Mybatis-Spring是基于SqlSessionFactoryBean的。在使用Mybatis-Spring的时候,我们也需要 SqlSession,而且这个SqlSession是内嵌在程序中的,一般不需要我们直接访问。SqlSession也是由 SqlSessionFactory来产生的,但是Mybatis-Spring给我们封装了一个SqlSessionFactoryBean,在这个 bean里面还是通过SqlSessionFactoryBuilder来建立对应的SqlSessionFactory,进而获取到对应的 SqlSession。通过SqlSessionFactoryBean我们可以通过对其指定一些属性来提供Mybatis的一些配置信息。所以接下来我 们需要在Spring的applicationContext配置文件中定义一个SqlSessionFactoryBean。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
       <property name="dataSource" ref="dataSource" />  
       <property name="mapperLocations"  
              value="classpath:com/tiantian/ckeditor/mybatis/mappers/*Mapper.xml" />  
       <property name="typeAliasesPackage" value="com.tiantian.ckeditor.model" />  
</bean>

       在定义SqlSessionFactoryBean的时候,dataSource属性是必须指定的,它表示用于连接数据库的数据源。当然,我们也可以指定一些其他的属性,下面简单列举几个:

  •  mapperLocations:它表示我们的Mapper文件存放的位置,当我们的Mapper文件跟对应的Mapper接口处于同一位置的时候可以不用指定该属性的值。

  • configLocation:用于指定Mybatis的配置文件位置。如果指定了该属性,那么会以该配置文件的内容作为配置信息构建对应的SqlSessionFactoryBuilder,但是后续属性指定的内容会覆盖该配置文件里面指定的对应内容。

  •  typeAliasesPackage:它一般对应我们的实体类所在的包,这个时候会自动取对应包中不包括包名的简单类名作为包括包名的别名。多个package之间可以用逗号或者分号等来进行分隔。

  •  typeAliases:数组类型,用来指定别名的。指定了这个属性后,Mybatis会把这个类型的短名称作为这个类型的别名,前提是该类上没有标注@Alias注解,否则将使用该注解对应的值作为此种类型的别名。

                      com.tiantian.mybatis.model.Blog           com.tiantian.mybatis.model.Comment         

  • plugins:数组类型,用来指定Mybatis的Interceptor。

  • typeHandlersPackage:用来指定TypeHandler所在的包,如果指定了该属性,SqlSessionFactoryBean会自动把该包下面的类注册为对应的TypeHandler。多个package之间可以用逗号或者分号等来进行分隔。

  • typeHandlers:数组类型,表示TypeHandler。

  接 下来就是在Spring的applicationContext文件中定义我们想要的Mapper对象对应的MapperFactoryBean了。通过 MapperFactoryBean可以获取到我们想要的Mapper对象。MapperFactoryBean实现了Spring的 FactoryBean接口,所以MapperFactoryBean是通过FactoryBean接口中定义的getObject方法来获取对应的 Mapper对象的。在定义一个MapperFactoryBean的时候有两个属性需要我们注入,一个是Mybatis-Spring用来生成实现了 SqlSession接口的SqlSessionTemplate对象的sqlSessionFactory;另一个就是我们所要返回的对应的 Mapper接口了。

        定义好相应Mapper接口对应的MapperFactoryBean之后,我们就可以把我们对应的Mapper接口注入到由Spring管理的bean 对象中了,比如Service  bean对象。这样当我们需要使用到相应的Mapper接口时,MapperFactoryBean会从它的getObject方法中获取对应的 Mapper接口,而getObject内部还是通过我们注入的属性调用SqlSession接口的getMapper(Mapper接口)方法来返回对 应的Mapper接口的。这样就通过把SqlSessionFactory和相应的Mapper接口交给Spring管理实现了Mybatis跟 Spring的整合。

Spring的applicationContext.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:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
     http://www.springframework.org/schema/context  
   http://www.springframework.org/schema/context/spring-context-3.0.xsd  
     http://www.springframework.org/schema/mvc  
     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
    <context:component-scan base-package="com.tiantian.mybatis"/>  
    <context:property-placeholder location="classpath:config/jdbc.properties"/>  
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
       destroy-method="close">  
       <property name="driverClassName" value="${jdbc.driver}" />  
       <property name="url" value="${jdbc.url}" />  
       <property name="username" value="${jdbc.username}" />  
       <property name="password" value="${jdbc.password}" />  
    </bean>  
   
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
       <property name="dataSource" ref="dataSource" />  
       <property name="mapperLocations" value="classpath:com/tiantian/mybatis/mapper/*.xml"/>  
       <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />  
    </bean>  
   
    <bean id="blogMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">  
       <property name="mapperInterface"  
           value="com.tiantian.mybatis.mapper.BlogMapper" />  
       <property name="sqlSessionFactory" ref="sqlSessionFactory" />  
    </bean>  
   
</beans>

BlogMapper.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="com.tiantian.mybatis.mapper.BlogMapper">  
<!--  新增记录  -->  
    <insert id="insertBlog" parameterType="Blog" useGeneratedKeys="true" keyProperty="id">  
        insert into t_blog(title,content,owner) values(#{title},#{content},#{owner})  
    </insert>  
<!--  查询单条记录  -->  
    <select id="selectBlog" parameterType="int" resultMap="BlogResult">  
       select * from t_blog where id = #{id}  
    </select>  
<!--  修改记录  -->  
    <update id="updateBlog" parameterType="Blog">  
        update t_blog set title = #{title},content = #{content},owner = #{owner} where id = #{id}  
    </update>  
<!--  查询所有记录  -->  
    <select id="selectAll" resultType="Blog">  
        select * from t_blog  
    </select>  
<!--  删除记录  -->  
    <delete id="deleteBlog" parameterType="int">  
       delete from t_blog where id = #{id}  
    </delete>  
     
</mapper>

BlogMapper.java****:

package com.tiantian.mybatis.mapper;  
   
import java.util.List;  
import com.tiantian.mybatis.model.Blog;  
   
publicinterface BlogMapper {  
   
    public Blog selectBlog(int id);  
     
    publicvoid insertBlog(Blog blog);  
     
    publicvoid updateBlog(Blog blog);  
     
    publicvoid deleteBlog(int id);  
     
    public List<Blog> selectAll();  
     
}

BlogServiceImpl.java****:

package com.tiantian.mybatis.service.impl;  
   
import java.util.List;  
import javax.annotation.Resource;  
import org.springframework.stereotype.Service;  
import com.tiantian.mybatis.mapper.BlogMapper;  
import com.tiantian.mybatis.model.Blog;  
import com.tiantian.mybatis.service.BlogService;  
   
@Service  
publicclass BlogServiceImpl implements BlogService {  
   
    private BlogMapper blogMapper;  
     
    publicvoid deleteBlog(int id) {  
       blogMapper.deleteBlog(id);  
    }  
   
    public Blog find(int id) {  
       returnblogMapper.selectBlog(id);  
    }  
   
    public List<Blog> find() {  
       returnblogMapper.selectAll();  
    }  
   
    publicvoid insertBlog(Blog blog) {  
       blogMapper.insertBlog(blog);  
    }  
   
    publicvoid updateBlog(Blog blog) {  
       blogMapper.updateBlog(blog);  
    }  
   
    public BlogMapper getBlogMapper() {  
       returnblogMapper;  
    }  
   
    @Resource  
    publicvoid setBlogMapper(BlogMapper blogMapper) {  
       this.blogMapper = blogMapper;  
    }  
   
}

MapperScannerConfigurer

        利用上面的方法进行整合的时候,我们有一个Mapper就需要定义一个对应的MapperFactoryBean,当我们的Mapper比较少的时候,这 样做也还可以,但是当我们的Mapper相当多时我们再这样定义一个个Mapper对应的MapperFactoryBean就显得速度比较慢了。为此 Mybatis-Spring为我们提供了一个叫做MapperScannerConfigurer的类,通过这个类Mybatis-Spring会自动 为我们注册Mapper对应的MapperFactoryBean对象。

        如果我们需要使用MapperScannerConfigurer来帮我们自动扫描和注册Mapper接口的话我们需要在Spring的 applicationContext配置文件中定义一个MapperScannerConfigurer对应的bean。对于 MapperScannerConfigurer而言有一个属性是我们必须指定的,那就是basePackage。basePackage是用来指定 Mapper接口文件所在的基包的,在这个基包或其所有子包下面的Mapper接口都将被搜索到。多个基包之间可以使用逗号或者分号进行分隔。最简单的 MapperScannerConfigurer定义就是只指定一个basePackage属性,如:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
   <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
</bean>

        这样MapperScannerConfigurer就会扫描指定基包下面的所有接口,并把它们注册为一个个MapperFactoryBean对象。当 使用MapperScannerConfigurer加basePackage属性的时候,我们上面例子的applicationContext配置文件 将变为这样:

<?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:mvc="http://www.springframework.org/schema/mvc"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
     http://www.springframework.org/schema/context  
     http://www.springframework.org/schema/context/spring-context-3.0.xsd  
     http://www.springframework.org/schema/mvc  
     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
   
    <context:component-scan base-package="com.tiantian.mybatis" />  
    <context:property-placeholder location="classpath:config/jdbc.properties" />  
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
       destroy-method="close">  
       <property name="driverClassName" value="${jdbc.driver}" />  
       <property name="url" value="${jdbc.url}" />  
       <property name="username" value="${jdbc.username}" />  
       <property name="password" value="${jdbc.password}" />  
    </bean>  
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
       <property name="dataSource" ref="dataSource" />  
       <property name="mapperLocations" value="classpath:com/tiantian/mybatis/mapper/*.xml" />  
       <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />  
    </bean>  
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
       <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
    </bean>  
</beans>

有时候我们指定的基包下面的并不全是我们定义的Mapper接口,为此MapperScannerConfigurer还为我们提供了另外两个可以缩小搜索和注册范围的属性。一个是annotationClass,另一个是markerInterface。

  • annotationClass:当指定了annotationClass的时候,MapperScannerConfigurer将只注册使用了annotationClass注解标记的接口。

  • markerInterface:markerInterface是用于指定一个接口的,当指定了markerInterface之后,MapperScannerConfigurer将只注册继承自markerInterface的接口。

如果上述两个属性都指定了的话,那么MapperScannerConfigurer将取它们的并集,而不是交集。即使用了annotationClass进行标记或者继承自markerInterface的接口都将被注册为一个MapperFactoryBean。

现在假设我们的Mapper接口都继承了一个SuperMapper接口,那么我们就可以这样来定义我们的MapperScannerConfigurer。

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
   <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
   <property name="markerInterface" value="com.tiantian.mybatis.mapper.SuperMapper"/>  
</bean>

       如果是都使用了注解MybatisMapper标记的话,那么我们就可以这样来定义我们的MapperScannerConfigurer。

       MybatisMapper的代码

package com.tiantian.mybatis.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MybatisMapper {
}

       xml的配置

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
   <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
   <property name="annotationClass" value="com.tiantian.mybatis.annotation.MybatisMapper"/>  
</bean>

        除了用于缩小注册Mapper接口范围的属性之外,我们还可以指定一些其他属性,如:

  • sqlSessionFactory:这个属性已经废弃。 当我们使用了多个数据源的时候我们就需要通过sqlSessionFactory来指定在注册MapperFactoryBean的时候需要使用的 SqlSessionFactory,因为在没有指定sqlSessionFactory的时候,会以Autowired的方式自动注入一个。换言之当我 们只使用一个数据源的时候,即只定义了一个SqlSessionFactory的时候我们就可以不给MapperScannerConfigurer指定 SqlSessionFactory。

  • sqlSessionFactoryBeanName:它的功能跟sqlSessionFactory是一样的,只是它指定的是定义好的SqlSessionFactory对应的bean名称。

  • sqlSessionTemplate:这个属性已经废弃。 它的功能也是相当于sqlSessionFactory的,因为就像前面说的那样,MapperFactoryBean最终还是使用的 SqlSession的getMapper方法取的对应的Mapper对象。当定义有多个SqlSessionTemplate的时候才需要指定它。对于 一个MapperFactoryBean来说SqlSessionFactory和SqlSessionTemplate只需要其中一个就可以了,当两者 都指定了的时候,SqlSessionFactory会被忽略。

  • sqlSessionTemplateBeanName:指定需要使用的sqlSessionTemplate对应的bean名称。

注意:由 于使用sqlSessionFactory和sqlSessionTemplate属性时会使一些内容在 PropertyPlaceholderConfigurer之前加载,导致在配置文件中使用到的外部属性信息无法被及时替换而出错,因此官方现在新的 Mybatis-Spring中已经把sqlSessionFactory和sqlSessionTemplate属性废弃了,推荐大家使用 sqlSessionFactoryBeanName属性和sqlSessionTemplateBeanName属性。

<?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:mvc="http://www.springframework.org/schema/mvc"  
    xmlns:mybatis="http://www.mybatis.org/schema/mybatis"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
     http://www.springframework.org/schema/context  
     http://www.springframework.org/schema/context/spring-context-3.0.xsd  
     http://www.mybatis.org/schema/mybatis  
     http://www.mybatis.org/schema/mybatis/mybatis-spring.xsd  
     http://www.springframework.org/schema/mvc  
     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
   
    <context:component-scan base-package="com.tiantian.mybatis" />  
    <context:property-placeholder location="classpath:config/jdbc.properties" />  
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"  
       destroy-method="close">  
       <property name="driverClassName" value="${jdbc.driver}" />  
       <property name="url" value="${jdbc.url}" />  
       <property name="username" value="${jdbc.username}" />  
       <property name="password" value="${jdbc.password}" />  
    </bean>  
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
       <property name="dataSource" ref="dataSource" />  
       <property name="mapperLocations" value="classpath:com/tiantian/mybatis/mapper/*.xml" />  
       <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />  
    </bean>  
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
       <property name="basePackage" value="com.tiantian.mybatis.mapper" />  
       <property name="markerInterface" value="com.tiantian.mybatis.mapper.SuperMapper"/>  
       <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>  
    </bean>  
</beans>

SqlSessionTemplate

        除了上述整合之后直接使用Mapper接口之外,Mybatis-Spring还为我们提供了一种直接使用SqlSession的方式。Mybatis- Spring为我们提供了一个实现了SqlSession接口的SqlSessionTemplate类,它是线程安全的,可以被多个Dao同时使用。同 时它还跟Spring的事务进行了关联,确保当前被使用的SqlSession是一个已经和Spring的事务进行绑定了的。而且它还可以自己管理 Session的提交和关闭。当使用了Spring的事务管理机制后,SqlSession还可以跟着Spring的事务一起提交和回滚。

       使用SqlSessionTemplate时我们可以在Spring的applicationContext配置文件中如下定义:

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

       这样我们就可以通过Spring的依赖注入在Dao中直接使用SqlSessionTemplate来编程了,这个时候我们的Dao可能是这个样子:

package com.tiantian.mybatis.dao;  
   
import java.util.List;  
import javax.annotation.Resource;  
import org.mybatis.spring.SqlSessionTemplate;  
import org.springframework.stereotype.Repository;  
import com.tiantian.mybatis.model.Blog;  
   
@Repository  
publicclass BlogDaoImpl implements BlogDao {  
   
    private SqlSessionTemplate sqlSessionTemplate;  
   
    publicvoid deleteBlog(int id) {  
       sqlSessionTemplate.delete("com.tiantian.mybatis.mapper.BlogMapper.deleteBlog", id);  
    }  
   
    public Blog find(int id) {  
      returnsqlSessionTemplate.selectOne("com.tiantian.mybatis.mapper.BlogMapper.selectBlog", id);  
    }  
   
    public List<Blog> find() {  
       returnthis.sqlSessionTemplate.selectList("com.tiantian.mybatis.mapper.BlogMapper.selectAll");  
    }  
   
    publicvoid insertBlog(Blog blog) {  
       this.sqlSessionTemplate.insert("com.tiantian.mybatis.mapper.BlogMapper.insertBlog", blog);  
    }  
   
    publicvoid updateBlog(Blog blog) {  
       this.sqlSessionTemplate.update("com.tiantian.mybatis.mapper.BlogMapper.updateBlog", blog);  
    }  
     
    public SqlSessionTemplate getSqlSessionTemplate() {  
       returnsqlSessionTemplate;  
    }  
     
    @Resource  
    publicvoid setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {  
       this.sqlSessionTemplate = sqlSessionTemplate;  
    }  
   
}
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
5个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这