Spring integrates myBatis

Spring integration with myBatis

Core usage:

1. Configure SqlSessionFactoryBean

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

2. Configure MapperFactoryBean

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.niuh.mybatis.dao.UserMapper"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
Copy the code

3. Obtain the mapper object and execute the business method

context = new ClassPathXmlApplicationContext("spring.xml");
UserMapper mapper = context.getBean(UserMapper.class);
System.out.println(mapper.selectByid(1));
Copy the code

Object description: FactoryBean Factory beans are used to customize the generated Bean object. When an instance of a FactoryBean is configured in ioc, the Bean ID corresponds to the factoryBean.getobject () instance. SqlSessionFactoryBean: Generates an instance of SqlSessionFactory, which is a singleton object for the entire application lifecycle. Common attributes are as follows:

  • DataSource: dataSource (required)
  • ConfigLocation: specify the contents of mybatis-config. XML, but its Settings will be invalid (optional)
  • MapperLocations: specifies the path of mapper. XML, equivalent to the configuration of elements in mybatis-config. XML. (Optional)

MapperFactoryBean: Generates the corresponding Mapper object, usually a singleton, for the entire application life cycle. Common attributes are as follows:

  • MapperInterface: Mapper interface (Mandatory)
  • SqlSessionFactory: session factory instance reference (required)

Is there a thread-safe problem with Mapper singletons? In native myBatis use mapper object life is synchronized with SqlSession, there is no thread safety problem, now singleton mapper is how to solve the problem of thread safety?

Core process analysis:

SQL Session integration structure:

Initialize process // Create session template SqlSessionTemplate

>org.mybatis.spring.mapper.MapperFactoryBean#MapperFactoryBean()
>org.mybatis.spring.support.SqlSessionDaoSupport#setSqlSessionFactory
>org.mybatis.spring.SqlSessionTemplate#SqlSessionTemplate()
>org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor 
Copy the code

// Create an interface

>org.mybatis.spring.mapper.MapperFactoryBean#getObject
>org.mybatis.spring.SqlSessionTemplate#getMapper
>org.apache.ibatis.session.Configuration#getMapper
Copy the code

// Execute the query

>com.niuh.mybatis.dao.UserMapper#selectByid
>org.apache.ibatis.binding.MapperProxy#invoke
>org.mybatis.spring.SqlSessionTemplate#selectOne(java.lang.String)
>org.mybatis.spring.SqlSessionTemplate#sqlSessionProxy#selectOne(java.lang.String)
>org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke
>org.mybatis.spring.SqlSessionUtils#getSqlSession()
>org.apache.ibatis.session.SqlSessionFactory#openSession()
>org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne()
Copy the code

Each query creates a new SqlSession session. Does level 1 caching still work? We learned earlier that the condition for level 1 caching is the same session, so caching won’t take effect once it’s integrated with Spring. No session is being recreated unless spring transactions are used.

Use of things:

Spring things do not have a configuration for myBatis, are some general things configuration:

<! Add transaction configuration --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg ref="dataSource"/> </bean> <! <tx:annotation-driven/>Copy the code

Add notes to things:

@Transactional()
public User getUser2(Integer id) {
    userMapper.selectByid(id);
    return userMapper.selectByid(id);
}
Copy the code

The execution of the test found that the two queries did not create the sqlSession repeatedly when the getUser2 method was called. Instead, they share one until the end of the getUser2 method.

Transaction and SqlSession integration principle: its principle is involved in the query process. The session is obtained through getSqlSession before each SQL operation. The main logic is that if something exists in the current thread and there is an associated session, it is fetched from ThreadLocal. If not, create a SqlSession and store it in ThreadLocal for the next query. Related source code:

>org.mybatis.spring.SqlSessionUtils#getSqlSession()
>org.springframework.transaction.support.TransactionSynchronizationManager#getResource
>org.mybatis.spring.SqlSessionUtils#sessionHolder
>org.apache.ibatis.session.SqlSessionFactory#openSession()
>org.mybatis.spring.SqlSessionUtils#registerSessionHolder
>org.springframework.transaction.support.TransactionSynchronizationManager#isSynchronizationActive
>org.springframework.transaction.support.TransactionSynchronizationManager#bindResource
Copy the code

Simplified Mapper configuration

If every Mapper interface is configured with MapperFactoryBean, it is quite troublesome to automatically scan through the following configuration

 <mybatis:scan base-package="com.niuh.mybatis.dao"/>
Copy the code

This is similar to the Spring Bean annotation scanning mechanism, so the configuration of the annotation scanning switch is required

<context:annotation-config/>
Copy the code