A brief analysis of the implementation process of mybatis and spring integration

  • 2020-04-01 04:18:52
  • OfStack

According to the official statement, before ibatis3, also known as Mybatis3, the development of Spring3 has been completed, so there is still no support for Mybatis3 in Spring3. Therefore, Mybatis community developed a Mybatis - Spring to meet the needs of Mybatis users to integrate Spring. The following will be through Mybatis-Spring to integrate the use of Mybatis and Spring to do a simple introduction.

MapperFactoryBean

First, we need to download the Mybatis-Spring jar from the Mybatis official website and add it to the classpath of our project. Of course, we also need to add the Mybatis related jar and Spring related jar. We know that all operations in Mybatis are based on a SqlSession, and SqlSession is generated by SqlSessionFactory, SqlSessionFactory is generated by SqlSessionFactoryBuilder. But Mybatis-Spring is based on SqlSessionFactoryBean. When using Mybatis-Spring, we also need SqlSession, and this SqlSession is embedded in the program, generally do not need us to access directly. SqlSession is also generated by SqlSessionFactory, but Mybatis-Spring gives us a package of SqlSessionFactoryBean, in this bean or through SqlSessionFactoryBuilder to establish the corresponding SqlSessionFactory, and then get the corresponding SqlSession. Through SqlSessionFactoryBean, we can provide some configuration information of Mybatis by specifying some properties to it. So next we need to define an SqlSessionFactoryBean in Spring's applicationContext configuration file.

Xml code


<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> 

            When defining the SqlSessionFactoryBean, the dataSource property must be specified to represent the dataSource used to connect to the database. Of course, we can specify some other properties as well, just to name a few:

  MapperLocations: it indicates the location of our Mapper file, so we don't have to specify the value of this property when our Mapper file is in the same location as the corresponding Mapper interface.

ConfigLocation: used to specify the configuration file location for Mybatis. If the property is specified, the corresponding SqlSessionFactoryBuilder is built with the contents of the configuration file as the configuration information, but the contents specified by the subsequent properties override the corresponding contents specified in the configuration file.

  TypeAliasesPackage: this usually corresponds to the package in which our entity class is located. At this time, the simple class name that does not include the package name in the corresponding package is automatically taken as the alias of the package name. Multiple packages can be separated by commas, semicolons, etc.
  TypeAliases: array type used to specify aliases. When this property is specified, Mybatis aliases the short name of the type, provided that the @alias annotation is not annotated on the class, otherwise the value corresponding to the annotation is used as the Alias of the type.

Xml code


<property name="typeAliases"> 
 <array> 
 <value>com.tiantian.mybatis.model.Blog</value> 
 <value>com.tiantian.mybatis.model.Comment</value> 
 </array> 
</property> 

Plugins: array type that specifies an Interceptor for Mybatis.

  TypeHandlersPackage: used to specify the package in which the TypeHandler resides. If this property is specified, the SqlSessionFactoryBean automatically registers the classes under the package as the corresponding TypeHandler. Multiple packages can be separated by commas, semicolons, etc.

  TypeHandlers: an array type that represents a TypeHandler.

The next step is to define the MapperFactoryBean for the Mapper object we want in the Spring applicationContext file. Through MapperFactoryBean, we can get the Mapper object we want. MapperFactoryBean implements the FactoryBean interface of Spring, so MapperFactoryBean gets the corresponding Mapper object through the getObject method defined in the FactoryBean interface. When defining a MapperFactoryBean, we need to inject two properties. One is the sqlSessionFactory used by Mybatis-Spring to generate SqlSessionTemplate object that implements SqlSession interface. The other one is the Mapper interface that we're going to return.

After defining the MapperFactoryBean for the corresponding Mapper interface, we can inject our corresponding Mapper interface into the spring-managed bean object, such as the Service bean object. In this way, when we need to use the corresponding Mapper interface, MapperFactoryBean will get the corresponding Mapper interface from its getObject method, and getObject will return the corresponding Mapper interface by calling the getMapper(Mapper interface) method of SqlSession interface through the properties we injected. In this way, the integration of Mybatis and Spring is realized by giving SqlSessionFactory and the corresponding Mapper interface to Spring management.

Spring's applicationcontext.xml configuration file:

Xml code


<?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 file:

Xml code


<?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"> 
<!--  The new record  --> 
 <insert id="insertBlog" parameterType="Blog" useGeneratedKeys="true" keyProperty="id"> 
  insert into t_blog(title,content,owner) values(#{title},#{content},#{owner}) 
 </insert> 
<!--  Query a single record  --> 
 <select id="selectBlog" parameterType="int" resultMap="BlogResult"> 
  select * from t_blog where id = #{id} 
 </select> 
<!--  Modify the record  --> 
 <update id="updateBlog" parameterType="Blog"> 
  update t_blog set title = #{title},content = #{content},owner = #{owner} where id = #{id} 
 </update> 
<!--  Query all records  --> 
 <select id="selectAll" resultType="Blog"> 
  select * from t_blog 
 </select> 
<!--  Delete records  --> 
 <delete id="deleteBlog" parameterType="int"> 
  delete from t_blog where id = #{id} 
 </delete> 
</mapper> 

BlogMapper. Java:

Java code


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:

Java code


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

When the above method is used for integration, we need to define a corresponding MapperFactoryBean when we have a Mapper. This is ok when we have relatively few mappers, but it is slow to define mapperfactorybeans corresponding to a Mapper when we have a large number of mappers. For this reason, Mybatis-Spring provides us with a class called MapperScannerConfigurer, through which Mybatis-Spring will automatically register the MapperFactoryBean object corresponding to Mapper for us.

If we need to use MapperScannerConfigurer to automatically scan and register the Mapper interface we need to define a bean corresponding to MapperScannerConfigurer in the Spring applicationContext configuration file. For MapperScannerConfigurer there is one property that we must specify, and that is the basePackage. BasePackage is used to specify the basePackage where the Mapper interface file resides, and the Mapper interface is searched under this basePackage or all of its subpackages. Multiple base packages can be separated by commas or semicolons. The simplest MapperScannerConfigurer definition is to specify only one basePackage attribute, such as:

Xml code


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

The MapperScannerConfigurer then scans all the interfaces under the specified base package and registers them as MapperFactoryBean objects. When using the MapperScannerConfigurer plus the basePackage property, the applicationContext profile for our example above will look like this:

Xml code


<?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> 

  Sometimes the base packages we specify are not all the Mapper interfaces we defined, so MapperScannerConfigurer also provides us with two other properties that can narrow down the search and registration scope. One is annotationClass, and the other is markerInterface.

AnnotationClass: when an annotationClass is specified, the MapperScannerConfigurer will only register the interface that USES the annotationClass annotation tag.

MarkerInterface: markerInterface is used to specify an interface, and when markerInterface is specified, the MapperScannerConfigurer will only register the interface inherited from markerInterface.

If both properties are specified, the MapperScannerConfigurer will take their union, not their intersection. Even the interfaces annotated with the annotationClass or inherited from markerInterface will be registered as a MapperFactoryBean.

Now suppose that all of our Mapper interfaces inherit from a SuperMapper interface, then we can define our MapperScannerConfigurer in this way.

Xml code


<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> 

          If the annotation MybatisMapper tag is used, then we can define our MapperScannerConfigurer in this way.

Xml code


<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> 

In addition to the properties used to narrow down the scope of the registered Mapper interface, we can specify other properties, such as:

SqlSessionFactory: this property is deprecated. When we use multiple data sources, we need to use sqlSessionFactory to specify the sqlSessionFactory to be used when registering MapperFactoryBean, because when sqlSessionFactory is not specified, it will be automatically injected in the way of Autowired. In other words, when we only use one data source, that is, only one SqlSessionFactory is defined, we can not specify SqlSessionFactory to MapperScannerConfigurer.

SqlSessionFactoryBeanName: its function is the same with sqlSessionFactory, except that it specifies the defined sqlSessionFactory corresponding bean name.

SqlSessionTemplate: this property is deprecated. Its function is also equivalent to sqlSessionFactory, because, as mentioned earlier, MapperFactoryBean is ultimately the Mapper object that is retrieved from the getMapper method of SqlSession. You only need to specify it when the definition has multiple sqlsessiontemplates. For a MapperFactoryBean, only one of the SqlSessionFactory and SqlSessionTemplate is needed, and when both are specified, the SqlSessionFactory is ignored.

SqlSessionTemplateBeanName: specify the need to use sqlSessionTemplate corresponding bean name.
Note: Due to the use of sqlSessionFactory and sqlSessionTemplate attributes will make some content is accomplished before loading, cause in the configuration file to use external attribute information cannot be timely replacement and error, so the official new Mybatis - Spring has now sqlSessionFactory and sqlSessionTemplate attribute abandoned, Recommend to use sqlSessionFactoryBeanName sqlSessionTemplateBeanName and attribute.

Xml code  


<?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

In addition to using the Mapper interface directly after the above integration, Mybatis-Spring also provides us with a direct way to use SqlSession. Mybatis - Spring provides us with a SqlSessionTemplate class that implements the SqlSession interface. It is thread-safe and can be used by multiple daos at the same time. It is also associated with Spring transactions to ensure that the currently used SqlSession is one that is already bound to Spring transactions. It also manages Session commit and close itself. When Spring's transaction management mechanism is used, the SqlSession can also be committed and rolled back along with Spring's transactions.

When using SqlSessionTemplate, we can define it as follows in the Spring applicationContext configuration file:


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

            In this way, we can program directly using SqlSessionTemplate in Dao through Spring's dependency injection. At this time, our Dao might look like this:

Java code


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; 
 } 
} 

  Note:
  This paper is based on Mybatis3.2.1, Mybatis-Spring1.1.0 and Spring3.1.

Above is the brief analysis of mybatis and spring integration of this article to introduce the implementation process, I hope you like, the next article to introduce you   (link: #).


Related articles: