Four, mybatis third-party software integration source code parsing

A, spring integrated myBatis


Knowledge Point

  1. The core use
  2. The core flow analysis
  3. Use things
  4. Mapper simplifies configuration

1, the core use:

Integrated basis using:

  1. Configuration dataSource
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;rewriteBatchedStatements=true"></property>
    <property name="username" value="root"></property>
    <property name="password" value="root"></property>
</bean>
复制代码
  1. Configuration SqlSessionFactoryBean
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <!--<property name="configLocation" value="classpath:mybatis-config.xml"/>-->
    <!--<property name="mapperLocations" value="classpath:com/cyan/mapper/*.xml"></property>-->
</bean>
复制代码
  1. Configuration MapperFactoryBean
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.cyan.mapper.UserMapper"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
复制代码
  1. Create a mapper Interface (UserMapper)
@Select("select * from user where id=#{id}")
User selectUserById1(Integer id);
复制代码
  1. Gets mapper object to perform business method
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserMapper userMapper = context.getBean(UserMapper.class);
User user = userMapper.selectUserById1(1);
System.out.println(user);
复制代码

Core of instructions like:

FactoryBean : Bean plants, used to custom build Bean object, when arranged in ioc FactoryBean Examples, the final pass of FactoryBean.getObject corresponds bean id () example, instance itself not FactoryBean

The SqlSessionFactoryBean : generating SqlSessionFactory instance, singleton objects, acting across the application lifecycle. Common attributes are as follows:

  • dataSource: data source (required)
  • configLocation: mybatis-config.xml specified content, but its failure will be provided (optional)
  • mapperLocations: mapper.xml specified path, corresponding elements mybatis-config.xml configuration, (optional)

The MapperFactoryBean : generating a corresponding Mapper object, usually a single embodiment, applied to the entire application lifecycle. Common attributes are as follows:

  • mapperInterface: mapper Interface (required)
  • sqlSessionFactory: session factory instance reference (required)

Whether there is thread safe Singleton case under Mapper problem?

Use lifetime in mapper object in the native myBatis with SqlSession are synchronized, there will be no security thread, now mapper single example of how to solve thread safety problems?

2, the core flow analysis

SQL session integrated structure:

image

Initialization process

  1. Create session templates SqlSessionTemplate
> org.mybatis.spring.mapper.MapperFactoryBean#getObject()
> org.mybatis.spring.support.SqlSessionDaoSupport#getSqlSession()
> org.mybatis.spring.support.SqlSessionDaoSupport#setSqlSessionFactory()
> org.mybatis.spring.support.SqlSessionDaoSupport#createSqlSessionTemplate()
> org.mybatis.spring.SqlSessionTemplate#SqlSessionTemplate()
> org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor()
复制代码
  1. Creating interfaces
> org.mybatis.spring.mapper.MapperFactoryBean#getObject()
> org.mybatis.spring.SqlSessionTemplate#getMapper()
> org.apache.ibatis.session.Configuration#getMapper()
> org.apache.ibatis.binding.MapperRegistry#getMapper()
> org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)
复制代码
  1. Execute the query
> com.cyan.test#selectUserByid()
> org.apache.ibatis.binding.MapperProxy#invoke()
> org.mybatis.spring.SqlSessionTemplate#selectOne()
> org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#SqlSessionInterceptor()
> org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke()
> org.mybatis.spring.SqlSessionUtils#getSqlSession()
> org.apache.ibatis.session.SqlSessionFactory#openSession()

> org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne()
复制代码

One for every SqlSession create a new session, a cache will take effect right?

By previous lesson we learned: a cache of conditions must be the same session, so the cache by following spring and integration will not take effect. Unless a spring thing, then it will not be re-created in the session.

3, the use of things

spring things not for myBatis configuration, are some general things to configure:

<context:annotation-config/>

<context:component-scan base-package="com.cyan.service.**"/>

<!--添加事物配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!--开启事物注解-->
<tx:annotation-driven/>
复制代码

Add things Note:

@Transactional
public User selectUserById(Integer id) {
    userMapper.selectUserById(id);
    return userMapper.selectUserById(id);
}
复制代码

Perform tests found that when calling selectUserById () method to create two queries will not be repeated sqlSession. But a common end until selectUserById method.

Things and SqlSession integration principle:

Front principle when it comes to talking about some query process. Every time perform SQL operations will be acquired before the session by getSqlSession. The main logic is: if the current thread existence of things, and there is a correlation session, was taken from ThreadLocal, the session will be stored in the relevant session does not exist to create new ThreadLocal them for the next queries. If the current thread does not perform the transaction would create a SqlSession sql, not saved to the ThreadLocal them.

Related Items:

> org.mybatis.spring.SqlSessionUtils#getSqlSession()
> org.springframework.transaction.support.TransactionSynchronizationManager#getResource()
> org.springframework.transaction.support.TransactionSynchronizationManager#doGetResource()

> 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()
复制代码

4, a simplified configuration Mapper

If each mapper interfaces are configured MapperFactoryBean rather cumbersome, may be arranged automatically by scanning

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

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.cyan.mapper"></property>
</bean>
复制代码

Spring bean annotation with similar scanning mechanism, so have to add annotations scanner configuration of

<context:annotation-config/>
复制代码

Second, the dynamic SQL


Knowledge Point

  1. Dynamic command
  2. Custom template interpreter

1, dynamic command

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

, Example shows:

<select id="selectByUser" parameterType="com.cyan.pojo.User" resultType="com.cyan.pojo.User">
    select * from user
    <trim prefix="where" prefixOverrides="and|or">
        <if test="id !=null and id != ''">
            and id = #{id}
        </if>
        <if test="name !=null and name != ''">
            and name = #{name}
        </if>
    </trim>
</select>
复制代码

trim Property Description:

  • prefix = "where" // prefix
  • prefixOverrides = "and | or" // prefix to replace the word
  • suffix = "" // add the suffix
  • suffixOverrides = "" // suffix to replace the word

Element Description:

Will be automatically added in front of where the package and remove SQL where the character of end to end multi She and | or characters, the equivalent of the following configurations:

<trim prefix="where" prefixOverrides="and|or" suffixOverrides="and|or">

<select id="selectByUser" parameterType="com.cyan.pojo.User" resultType="com.cyan.pojo.User">
    select * from user
    <where>
        <if test="id !=null and id != ''">
            and id = #{id}
        </if>
        <if test="name !=null and name != ''">
            and name = #{name}
        </if>
    </where>
</select>
复制代码

,, Element Description:

Similar to the switch statement in java

<select id="selectUserByNameOrId" resultType="com.cyan.pojo.User">
    select * from user
    <where>
        <choose>
            <when test="id != null">
                and id = #{id}
            </when>
            <when test="name != null and name != ''">
                and name = #{name}
            </when>
            <otherwise>
                and id in (1,2,3)
            </otherwise>
        </choose>
    </where>
</select>
复制代码

Element Description:

Automatically adds the character set before the set end to end and remove the wrapped SQL plurality of She ',' character.

<update id="updateUserById" parameterType="com.cyan.pojo.User">
    update user
    <set>
        <if test="name != null and name != ''">
            name = #{name},
        </if>
        <if test="updateTime != null">
            update_time = #{updateTime}
        </if>
    </set>
    where id = #{id}
</update>
复制代码

Element Description:

Function foreach element is very powerful, it allows you to specify a collection, a collection of items (item) and index (index) statement can be used in variable elements of the body. It also allows you to specify the beginning and end of the string and placing the separator between the results of the iteration. This element is smart, so it will not accidentally append extra separators.

<select id="selectUserListByIds" resultType="com.cyan.pojo.User">
    select * from user
    <where>
        <if test="ids != null">
            id in
            <foreach collection="ids" item="item" index="index" open="(" close=")" separator=",">
                #{item}
            </foreach>
        </if>
    </where>
</select>
复制代码

Elements Description:

When a plurality of identical sections of the same plurality sql mapper statement, can be carried out by the element declaration referenced by the elements

<sql id="files">
    id,name,create_time,update_time
</sql>

<select id="selectUserById2" resultType="com.cyan.pojo.User" parameterType="int">
    select
    <include refid="files"></include>
    from user where id = #{id}
</select>
复制代码

Variables:

May require some additional logic operation, by declaring elements and add operation script attribute value thereof, the following example is automatically added to likeName% semicolon, then # {likeName} can be used with like semicolon% operations.

<select id="selectByUser" parameterType="com.cyan.pojo.User" resultType="com.cyan.pojo.User">
    <bind name="likename" value="'%'+_parameter.getName()+'%'"></bind>
    select * from user
    <trim prefix="where" prefixOverrides="and|or">
        <if test="id !=null and id != ''">
            and id = #{id}
        </if>
        <if test="name !=null and name != ''">
            and name like #{likename}
        </if>
    </trim>
</select>
复制代码

Built-in variables:

  • _databaseid database identifier ID
  • Current treatment parameter variations _parameter

2, custom template interpreter

Above if, trim, where logic and other operators are myBatis own interpretation of the language XMLLanguageDriver provided, in addition we also can use the MyBatis-Velocity or mybatis-freemarker and other external interpreter to write dynamic script.

mybatis-freemarker use:

Introducing jar package:

<dependency>
    <groupId>org.mybatis.scripting</groupId>
    <artifactId>mybatis-freemarker</artifactId>
    <version>1.2.0</version>
</dependency>
复制代码

Add sql statement

<select id="selectUserListByIds" resultType="com.cyan.pojo.User"
            lang="org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver">
    select * from user
    where  id in (${ids?join(',')})
</select>
复制代码

Adding interface method

List<User> selectUserListByIds(@Param("ids") List<Integer> ids);
复制代码

Guess you like

Origin juejin.im/post/5da30cb4f265da5b5e2d9c5c