1. 程式人生 > >TKmybatis的框架介紹和原理分析及Mybatis新特性演示

TKmybatis的框架介紹和原理分析及Mybatis新特性演示

tkmybatis是在mybatis框架的基礎上提供了很多工具,讓開發更加高效,下面來看看這個框架的基本使用,後面會對相關原始碼進行分析,感興趣的同學可以看一下,挺不錯的一個工具

實現對員工表的增刪改查的程式碼
java的dao層介面

public interface WorkerMapper extends Mapper<Worker> {
}

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.jjs.kaiwen.dao.WorkerMapper"> <resultMap id="BaseResultMap" type="com.jjs.kaiwen.model.Worker"> <!-- WARNING - @mbggenerated --> <id column="id" jdbcType="INTEGER" property="id" /> <result column="worker_id" jdbcType="VARCHAR"
property="workerId" />
<result column="name" jdbcType="VARCHAR" property="name" /> <result column="org_id" jdbcType="INTEGER" property="orgId" /> <result column="status" jdbcType="VARCHAR" property="status" /> <result column="role_id" property="roleId" jdbcType="INTEGER"
/>
</resultMap> </mapper>

實體物件

@Table(name = "worker")
public class Worker {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "worker_id")
    private String workerId;

    private String name;

    @Column(name = "org_id")
    private Integer orgId;

    private String status;

    @Column(name = "role_id")
    private Integer roleId;

    // getters and setters ...
    }

以上就是實現對Worker進行增刪改查的所有程式碼,包括選擇性更新、插入、刪除等,所有的方法列表如下

這裡寫圖片描述

以後對錶欄位的新增或修改只需要更改實體物件的註解,不需要修改xml對映檔案,如將worker_id改成worker_no

@Column(name = "worker_no")
private String workerNo;

資料來源的配置,只需要將org.mybatis.spring.mapper.MapperScannerConfigurer改成tk.mybatis.spring.mapper.MapperScannerConfigurer,然後加一個屬性
,也可不加,因為框架提供了預設實現

    <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <property name="basePackage" value="com.jjs.zanbi.dao" />
        <property name="properties">
            <value>
                mappers=tk.mybatis.mapper.common.Mapper
            </value>
        </property>
    </bean>

用這個庫之後寫程式碼感覺在飛…….如果只是簡單的瞭解此框架到這裡就可以了,下面是對框架實現原理的分析

原理的簡單分析

此框架為我們實現這些功能所有的改動都在Mapper層面,所有的Mapper都繼承了tk.mybatis.mapper.common.Mapper

public interface WorkerMapper extends Mapper<Worker> {}

Mapper介面的宣告如下,可以看到Mapper介面實現了所有常用的方法

public interface Mapper<T> extends
        BaseMapper<T>,
        ExampleMapper<T>,
        RowBoundsMapper<T>,
        Marker {

}

看一下完整的UML圖,太大了,可以用新視窗開啟,放大之後再看
這裡寫圖片描述

這裡選擇一個介面:SelectOneMapper介面,對於原始碼進行簡單分析,此介面宣告如下:

public interface SelectOneMapper<T> {

    /**
     * 根據實體中的屬性進行查詢,只能有一個返回值,有多個結果是丟擲異常,查詢條件使用等號
     *
     * @param record
     * @return
     */
    @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")
    T selectOne(T record);

}

@SelectProvider是mybatis3之後提供的,用於靈活的設定sql來源,這裡設定了服務提供類和方法,但這個庫並沒有直接用method指定的方法來返回sql,而是在執行時進行解析的,程式碼如下

public class BaseSelectProvider extends MapperTemplate {

    public String selectOne(MappedStatement ms) {
        Class<?> entityClass = getEntityClass(ms);
        //修改返回值型別為實體型別
        setResultType(ms, entityClass);
        StringBuilder sql = new StringBuilder();
        sql.append(SqlHelper.selectAllColumns(entityClass));
        sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
        sql.append(SqlHelper.whereAllIfColumns(entityClass, isNotEmpty()));
        return sql.toString();
    }
}

到這裡我們就大概知道了這個庫為我們提供便利的原理了,總的來說就是這個庫幫我們提供了對錶的基本操作的sql,幫我們省了很多工作量,而且維護起來也很方便,否則我們的xml檔案動不動就幾百行甚至上千行

對原始碼的探索不能到這裡停止,最起碼要分析到與另一個框架的整合點

我們知道,mybatis的mapper介面是在啟動的時候被框架以JdkProxy的形式封裝了的,具體對應的類是MapperFactoryBean,這個類中有一個checkDaoConfig()方法,是從父類繼承並重寫了該方法,繼承結構如下

MapperFactoryBean -> SqlSessionDaoSupport -> DaoSupport

這裡的DaoSupport就是spring提供的Dao的抽象,程式碼如下

public abstract class DaoSupport implements InitializingBean {

// spring 完成屬性設定後會呼叫此方法
    @Override
    public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
        // 這裡提供了介面供子類去實現
        checkDaoConfig();

        // Let concrete implementations initialize themselves.
        try {
            initDao();
        }
        catch (Exception ex) {
            throw new BeanInitializationException("Initialization of DAO failed", ex);
        }
    }

    protected abstract void checkDaoConfig() throws IllegalArgumentException;

    protected void initDao() throws Exception {
    }

}

框架自定義的MapperFactoryBean重寫了checkDaoConfig()方法,完成對所有sql語句的設定,程式碼如下

    @Override
    protected void checkDaoConfig() {
        super.checkDaoConfig();
        //通用Mapper
        if (mapperHelper.isExtendCommonMapper(getObjectType())) {
        //這裡去處理該類所對應的MappedStatement,封裝在helper類中處理
            mapperHelper.processConfiguration(getSqlSession().getConfiguration(), getObjectType());
        }
    }

MapperHelper的processConfiguration方法如下

    public void processConfiguration(Configuration configuration, Class<?> mapperInterface) {
        String prefix;
        if (mapperInterface != null) {
            prefix = mapperInterface.getCanonicalName();
        } else {
            prefix = "";
        }
        for (Object object : new ArrayList<Object>(configuration.getMappedStatements())) {
            if (object instanceof MappedStatement) {
                MappedStatement ms = (MappedStatement) object;
                //檢查這個MappedStatement是否屬於此對映物件
                if (ms.getId().startsWith(prefix) && isMapperMethod(ms.getId())) {
                    if (ms.getSqlSource() instanceof ProviderSqlSource) {
                       //去設定該statement的sql語句
                        setSqlSource(ms);
                    }
                }
            }
        }
    }

設定sql的邏輯,提供了幾種不同型別的sqlsource

    public void setSqlSource(MappedStatement ms) throws Exception {
        if (this.mapperClass == getMapperClass(ms.getId())) {
            throw new RuntimeException("請不要配置或掃描通用Mapper介面類:" + this.mapperClass);
        }
        Method method = methodMap.get(getMethodName(ms));
        try {
            //第一種,直接操作ms,不需要返回值
            if (method.getReturnType() == Void.TYPE) {
                method.invoke(this, ms);
            }
            //第二種,返回SqlNode
            else if (SqlNode.class.isAssignableFrom(method.getReturnType())) {
                SqlNode sqlNode = (SqlNode) method.invoke(this, ms);
                DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(ms.getConfiguration(), sqlNode);
                setSqlSource(ms, dynamicSqlSource);
            }
            //第三種,返回xml形式的sql字串
            else if (String.class.equals(method.getReturnType())) {
                String xmlSql = (String) method.invoke(this, ms);
                SqlSource sqlSource = createSqlSource(ms, xmlSql);
                //替換原有的SqlSource
                setSqlSource(ms, sqlSource);

到這裡整個sql的獲取流程就分析完了,本人用這個庫寫過一個小專案,確實節省了開發的工作量,而且DAO層的結構更加清晰簡潔了

關於mybatis新特性

從3.4.0開始,mybatis提供對外部表的alias引用方法,多表聯合查詢就方便多了,我們先看原始的方式是怎樣做的

select a.id,a.name,b.bid,b.bname .....
from user a 
left join room b 

原始的方式是將所有的表字段列出來,再來看用新特性怎樣做

select id="selectUsers" resultType="map">
  select
    <include refid="user_col_sql_id"><property name="alias" value="t1"/>,
    <include refid="room_col_sql_id"><property name="alias" value="t2"/>
  from user t1
    left join room t2
</select>

這裡主要就是對基本的sql進行了複用,如果對錶進行了修改只要在原始的sql節點修改就可以了,就算是5個表的聯合查詢,sql也是清晰易懂,維護起來會更輕鬆

新版本的mybatis對於物件對映也提供了更友好的方式,直接使用外部的ResultMap再加上查詢語句中的別名就對映完成了

    <resultMap id="workerResultMap" type="com.jjs.kaiwen.model.Worker" extends="BaseResultMap">
        <association property="room" columnPrefix="b_"  resultMap="com.jjs.kaiwen.dao.OrgMapper.BaseResultMap"/>
    </resultMap>

更進一步

敏銳的程式設計師可能會提出問題,如當多表查詢的時候可能會存在欄位名稱相同的情況,這裡的解決方案是給include新增另一個屬性

<include refid="user_col_sql_id_with_alias">
<property name="alias" value="t"/>
<property name="prefix" value="t_"/>
</include>

包含prefix的sqlNode如下

    <sql id="base_column_with_alias">
        ${alias}.ID as ${prefix}ID,
        ${alias}.WORKER_ID as ${prefix}WORKER_ID,
        ${alias}.NAME as ${prefix}NAME,
        ${alias}.ZB_ROLE_ID as ${prefix}ZB_ROLE_ID,
        ${alias}.ORG_ID as ${prefix}ORG_ID,
        ${alias}.STATUS as ${prefix}STATUS
    </sql>

如果說覺得手動寫包含alias和prefix的欄位麻煩,可以用,mybatis程式碼生成器的外掛的方式實現,我自己寫了一個生成器的外掛,可以程式碼再這裡,僅供參考

通用Service類

/**
 * Created by Kaiwen
 */
@Service
public abstract class CommonServiceImpl<T,PK extends Serializable> implements CommonService<T,PK> {
    /**
     * 泛型注入
     */
    @Autowired
    private Mapper<T> mapper;

    public T selectByPrimaryKey(PK entityId) {

        return mapper.selectByPrimaryKey(entityId);
    }

    public int deleteByPrimaryKey(PK entityId) {
        return mapper.deleteByPrimaryKey(entityId);
    }

    public int insert(T record) {
        return mapper.insert(record);
    }

    public int insertSelective(T record) {
        return mapper.insertSelective(record);
    }

    public int updateByPrimaryKeySelective(T record) {
        return mapper.updateByPrimaryKeySelective(record);
    }

    public int updateByPrimaryKey(T record) {
        return mapper.updateByPrimaryKey(record);
    }

    public List<T> selectByExample(Example example) {
        return mapper.selectByExample(example);
    }
}

注入方式區別

    <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <property name="basePackage" value="com.jjshome.esf.core.dao.school" />
        <property name="properties">
            <value>
                mappers=tk.mybatis.mapper.common.Mapper
            </value>
        </property>
    </bean>


    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.jjshome.esf.core.dao.community,com.jjshome.esf.core.dao.hsl"/>
    </bean>

實體類

package com.jjshome.esf.common.entity.school;

import java.util.Date;
import javax.persistence.*;

@Table(name = "XQ_SCHOOL_AREA")
public class SchoolArea {
    /**
     * 主鍵ID
     */
    @Id
    @Column(name = "ID")
    private Integer id;

    /**
     * 城市編碼
     */
    @Column(name = "CITY_CODE")
    private String cityCode;

    /**
     * 學區名稱
     */
    @Column(name = "NAME")
    private String name;

    /**
     * 學區名稱拼音
     */
    @Column(name = "NAME_SPELL")
    private String nameSpell;

    /**
     * 狀態,1:正常,0:刪除
     */
    @Column(name = "STATUS")
    private Byte status;

    /**
     * 新增人
     */
    @Column(name = "CREATE_ID")
    private String createId;


    @Transient
    private Integer primaryCount; //小學數量
    @Transient
    private Integer middleCount; //初中數量
    @Transient
    private Integer highCount;//高中數量

TK mybatis Mapper檔案內容

<?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.jjshome.esf.core.dao.school.ISchoolAreaDAO" >
  <resultMap id="BaseResultMap" type="com.jjshome.esf.common.entity.school.SchoolArea" >
    <!--
      WARNING - @mbggenerated
    -->
    <id column="ID" property="id" jdbcType="INTEGER" />
    <result column="CITY_CODE" property="cityCode" jdbcType="VARCHAR" />
    <result column="NAME" property="name" jdbcType="VARCHAR" />
    <result column="NAME_SPELL" property="nameSpell" jdbcType="VARCHAR" />
    <result column="STATUS" property="status" jdbcType="TINYINT" />
    <result column="CREATE_ID" property="createId" jdbcType="VARCHAR" />
    <result column="CREATE_DATE" property="createDate" jdbcType="TIMESTAMP" />
    <result column="UPDATE_ID" property="updateId" jdbcType="VARCHAR" />
    <result column="UPDATE_DATE" property="updateDate" jdbcType="TIMESTAMP" />
    <result column="CITY_NAME" property="cityName"/>
    <result column="PRIMARY_COUNT" property="primaryCount"/>
    <result column="MIDDLE_COUNT" property="middleCount"/>
    <result column="HIGH_COUNT" property="highCount"/>
  </resultMap>

    <resultMap id="SchoolDetailArea" type="com.jjshome.esf.common.entity.school.SchoolAreaDetail"
               extends="com.jjshome.esf.core.dao.school.ISchoolInfoDAO.SchoolInfo">
        <result column="SCHOOL_AREA_NAME" property="schoolAreaName"/>
    </resultMap>

    <select id="selectByPage" parameterType="map" resultMap="BaseResultMap">

        SELECT A.*, C.NAME AS CITY_NAME,
        (SELECT COUNT(*) FROM XQ_SCHOOL_INFO B WHERE A.ID=B.AREA_ID AND B.TYPE='553' AND B.STATUS = 1 ) AS PRIMARY_COUNT,
        (SELECT COUNT(*) FROM XQ_SCHOOL_INFO B WHERE A.ID=B.AREA_ID AND B.TYPE='554' AND B.STATUS = 1 ) AS MIDDLE_COUNT,
        (SELECT COUNT(*) FROM XQ_SCHOOL_INFO B WHERE A.ID=B.AREA_ID AND B.TYPE='555' AND B.STATUS = 1 ) AS HIGH_COUNT
        FROM XQ_SCHOOL_AREA A
        LEFT JOIN YW_CITY_SETTING C ON A.CITY_CODE = C.CODE
        <where>
            <if test="name != null and name != '' "> A.NAME LIKE CONCAT('%',#{NAME},'%')  </if>
            <if test="areaCityCode != null and areaCityCode != '' "> A.CITY_CODE = #{areaCityCode}  </if>
            <if test="keywords != null and keywords != '' ">
                ( A.NAME LIKE CONCAT('%',#{keywords},'%')
                )
            </if>
        </where>
    </select>


    <select id="selectAreaIdAndKeyWord" parameterType="java.util.Map" resultMap="BaseResultMap">
        SELECT
        *
        FROM
        XQ_SCHOOL_AREA
        WHERE
        1=1
        <if test="cityId != null">
            AND CITY_CODE=#{cityId}
        </if>
        <if test="key != null and key!=''">
            AND (NAME like CONCAT(#{key},'%' ) or NAME_SPELL like CONCAT(#{key},'%' ))
        </if>
        AND
        STATUS=1
        <if test="pageSize != null">
            limit #{pageSize}
        </if>
    </select>


    <!--查詢學區詳情列表-->
    <select id="selectAreaDetailByPage" parameterType="map" resultMap="SchoolDetailArea">

        SELECT A.* ,B.NAME AS SCHOOL_AREA_NAME ,C.NAME AS CITY_NAME,D.NAME AS AREA_NAME FROM XQ_SCHOOL_INFO A
        LEFT JOIN XQ_SCHOOL_AREA B ON A.AREA_ID = B.ID
        LEFT JOIN YW_CITY_SETTING C ON A.CITY_CODE = C.CODE
        LEFT JOIN YW_CITY_SETTING D ON A.AREA_CODE = D.CODE

        WHERE A.STATUS = 1 AND B.STATUS =1
        <if test="areaId != null and areaId.length() &gt; 0">  AND A.AREA_ID = #{areaId} </if>
        <if test="typeList != null and typeList.size &gt; 0">
            AND
            A.TYPE IN
            <foreach collection="typeList"  item="item" index="index" open="(" close=")" separator=",">
                #{item}
            </foreach>
        </if>
        <if test="name != null and name != '' "> AND   A.NAME LIKE CONCAT('%',#{name},'%')  </if>
    </select>

</mapper>

普通mybatisMapper檔案

<?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.jjshome.esf.core.dao.school.ISchoolInfoDAO">
    <resultMap id="SchoolInfo" type="com.jjshome.esf.common.entity.school.SchoolInfo">
        <id column="ID" property="id"/>
        <result column="NAME" property="name"/>
        <result column="NAME_SPELL" property="nameSpell"/>
        <result column="ALIAS" property="alias"/>
        <result column="ALIAS_SPELL" property="aliasSpell"/>
        <result column="TYPE" property="type" typeHandler="com.jjshome.esf.core.component.handler.DictValueTypeHandler"/>
        <result column="AREA_ID" property="areaId"/>
        <result column="CITY_CODE" property="cityCode"/>
        <result column="AREA_CODE" property="areaCode"/>
        <result column="ADDR" property="addr"/>
        <result column="START_TIME" property="startTime"/>
        <result column="MOTTO" property="motto"/>
        <result column="WEB_SITE" property="webSite"/>
        <result column="PHONE" property="phone"/>
        <result column="FEATURE" property="feature" typeHandler="com.jjshome.esf.core.component.handler.DictValueListTypeHandler"/>
        <result column="LNG" property="lng"/>
        <result column="LAT" property="lat"/>
        <result column="UNIT_PRICE" property="unitPrice"/>
        <result column="SALE_PRICE" property="salePrice"/>
        <result column="NATURE_TYPE" property="natureType" typeHandler="com.jjshome.esf.core.component.handler.DictValueTypeHandler"/>
        <result column="NATURE_CITY" property="natureCity" typeHandler="com.jjshome.esf.core.component.handler.DictValueTypeHandler"/>
        <result column="SCHOOL_DEGREE" property="schoolDegree"/>
        <result column="ENROL_DEGREE" property="enrolDegree"/>
        <result column="IMG_DEGREE" property="imgDegree"/>
        <result column="STATUS" property="status"/>
        <result column="CREATE_ID" property="createId"/>
        <result column="CREATE_DATE" property="createDate"/>
        <result column="UPDATE_ID" property="updateId"/>
        <result column="UPDATE_DATE" property="updateDate"/>

        <result column="CITY_NAME" property="cityName" />
        <result column="AREA_NAME" property="areaName" />
        <result column="SCHOOL_DISTRICT_NAME" property="schoolDistrictName" />
        <result column="SALE_COUNT" property="saleCount" />
    </resultMap>

    <sql id="Base_Column_List">
        ID,
        NAME,
        NAME_SPELL,
        ALIAS,
        ALIAS_SPELL,
        TYPE,
        AREA_ID,
        CITY_CODE,
        AREA_CODE,
        ADDR,
        START_TIME,
        MOTTO,
        WEB_SITE,
        PHONE,
        FEATURE,
        LNG,
        LAT,
        UNIT_PRICE,
        SALE_PRICE,
        NATURE_TYPE,
        NATURE_CITY,
        SCHOOL_DEGREE,
        ENROL_DEGREE,
        IMG_DEGREE,
        STATUS,
        CREATE_ID,
        CREATE_DATE,
        UPDATE_ID,
        UPDATE_DATE,
        SALE_COUNT,
        SALE_COUNT
    </sql>

    <select id="selectById" resultMap="SchoolInfo" parameterType="java.lang.Integer">
        SELECT
            i.*,
            yc.NAME as 'CITY_NAME',
            ya.NAME as 'AREA_NAME',
            xq.NAME as 'SCHOOL_DISTRICT_NAME'
        FROM
            XQ_SCHOOL_INFO i
            LEFT JOIN YW_CITY_SETTING yc ON i.CITY_CODE = yc.CODE
            LEFT JOIN YW_CITY_SETTING ya ON i.AREA_CODE = ya.CODE
            LEFT JOIN XQ_SCHOOL_AREA xq ON i.AREA_ID = xq.ID
        WHERE
            i.ID = #{id,jdbcType=INTEGER}
    </select>

    <delete id="deleteById" parameterType="java.util.Map">
        UPDATE
            XQ_SCHOOL_INFO
        SET
            STATUS = 0,
            UPDATE_ID = #{updateId},
            UPDATE_DATE = NOW()
        WHERE
            ID = #{id,jdbcType=INTEGER}
    </delete>

    <delete id="batchDeleteByIds" parameterType="java.util.Map">
        UPDATE
            XQ_SCHOOL_INFO
        SET
            STATUS = 0,
            UPDATE_ID = #{updateId},
            UPDATE_DATE = NOW()
        WHERE
        ID IN (${ids})
    </delete>

    <update id="deleteAreaRelation" parameterType="com.jjshome.esf.common.entity.school.SchoolInfo">
        update XQ_SCHOOL_INFO
            SET AREA_ID = NULL,
            UPDATE_DATE = NOW()
        WHERE
        ID = #{id}
    </update>

    <insert id="insert" parameterType="com.jjshome.esf.common.entity.school.SchoolInfo">
        <selectKey resultType="Integer" keyProperty="id">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO XQ_SCHOOL_INFO
            (NAME,
            NAME_SPELL,
            ALIAS,
            ALIAS_SPELL,
            TYPE,
            AREA_ID,
            CITY_CODE,
            AREA_CODE,
            ADDR,
            START_TIME,
            MOTTO,
            WEB_SITE,
            PHONE,
            FEATURE,
            LNG,
            LAT,
            UNIT_PRICE,
            SALE_PRICE,
            NATURE_TYPE,
            NATURE_CITY,
            SCHOOL_DEGREE,
            ENROL_DEGREE,
            IMG_DEGREE,
            STATUS,
            CREATE_ID,
            CREATE_DATE,
            UPDATE_ID,
            UPDATE_DATE)
        VALUES
            (#{name,jdbcType=VARCHAR},
            #{nameSpell,jdbcType=VARCHAR},
            #{alias,jdbcType=VARCHAR},
            #{aliasSpell,jdbcType=VARCHAR},
            #{type,jdbcType=INTEGER},
            #{areaId,jdbcType=INTEGER},
            #{cityCode,jdbcType=VARCHAR},
            #{areaCode,jdbcType=VARCHAR},
            #{addr,jdbcType=VARCHAR},
            #{startTime,jdbcType=DATE},
            #{motto,jdbcType=VARCHAR},
            #{webSite,jdbcType=VARCHAR},
            #{phone,jdbcType=VARCHAR},
            #{feature,jdbcType=VARCHAR},
            #{lng,jdbcType=DECIMAL},
            #{lat,jdbcType=DECIMAL},
            #{unitPrice},
            #{salePrice},
            #{natureType,jdbcType=INTEGER},
            #{natureCity,jdbcType=INTEGER},
            #{schoolDegree,jdbcType=INTEGER},
            #{enrolDegree,jdbcType=INTEGER},
            #{imgDegree,jdbcType=INTEGER},
            #{status,jdbcType=TINYINT},
            #{createId,jdbcType=VARCHAR},
            #{createDate,jdbcType=DATE},
            #{updateId,jdbcType=VARCHAR},
            #{updateDate,jdbcType=DATE})
    </insert>
    <insert id="insertSelective" parameterType="com.jjshome.esf.common.entity.school.SchoolInfo">
        <selectKey resultType="Integer" keyProperty="id">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO XQ_SCHOOL_INFO
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="name != null">
                NAME,
            </if>
            <if test="nameSpell != null">
                NAME_SPELL,
            </if>
            <if test="alias != null">
                ALIAS,
            </if>
            <if test="aliasSpell != null">
                ALIAS_SPELL,
            </if>
            <if test="type != null">
                TYPE,
            </if>
            <if test="areaId != null">
                AREA_ID,
            </if>
            <if test="cityCode != null">
                CITY_CODE,
            </if>
            <if test="areaCode != null">
                AREA_CODE,
            </if>
            <if test="addr != null">
                ADDR,
            </if>
            <if test="startTime != null">
                START_TIME,
            </if>
            <if test="motto != null">
                MOTTO,
            </if>
            <if test="webSite != null">
                WEB_SITE,
            </if>
            <if test="phone != null">
                PHONE,
            </if>
            <if test="feature != null">
                FEATURE,
            </if>
            <if test="lng != null">
                LNG,
            </if>
            <if test="lat != null">
                LAT,
            </if>
            <if test="UNIT_PRICE != null">
                UNIT_PRICE,
            </if>
            <if test="SALE_PRICE != null ">
                SALE_PRICE,
            </if>
            <if test="natureType != null">
                NATURE_TYPE,
            </if>
            <if test="natureCity != null">
                NATURE_CITY,
            </if>
            <if test="schoolDegree != null">
                SCHOOL_DEGREE,
            </if>
            <if test="enrolDegree != null">
                ENROL_DEGREE,
            </if>
            <if test="imgDegree != null">
                IMG_DEGREE,
            </if>
            <if test="status != null">
                STATUS,
            </if>
            <if test="createId != null">
                CREATE_ID,
            </if>
            <if test="createDate != null">
                CREATE_DATE,
            </if>
            <if test="updateId != null">
                UPDATE_ID,
            </if>
            <if test="updateDate != null">
                UPDATE_DATE,
            </if>
        </trim>
        <trim prefix="VALUES (" suffix=")" suffixOverrides=",">
            <if test="name != null">
                #{name,jdbcType=VARCHAR},
            </if>
            <if test="nameSpell != null">
                #{nameSpell,jdbcType=VARCHAR},
            </if>
            <if test="alias != null">
                #{alias,jdbcType=VARCHAR},
            </if>
            <if test="aliasSpell != null">
                #{aliasSpell,jdbcType=VARCHAR},
            </if>
            <if test="type != null">
                #{type,jdbcType=INTEGER},
            </if>
            <if test="areaId != null">
                #{areaId,jdbcType=INTEGER},
            </if>
            <if test="cityCode != null">
                #{cityCode,jdbcType=VARCHAR},
            </if>
            <if test="areaCode != null">
                #{areaCode,jdbcType=VARCHAR},
            </if>
            <if test="addr != null">
                #{addr,jdbcType=VARCHAR},
            </if>
            <if test="startTime != null">
                #{startTime,jdbcType=DATE},
            </if>
            <if test="motto != null">
                #{motto,jdbcType=VARCHAR},
            </if>
            <if test="webSite != null">
                #{webSite,jdbcType=VARCHAR},
            </if>
            <if test="phone != null">
                #{phone,jdbcType=VARCHAR},
            </if>
            <if test="feature != null">
                #{feature,jdbcType=VARCHAR},
            </if>
            <if test="lng != null">
                #{lng,jdbcType=DECIMAL},
            </if>
            <if test="lat != null">
                #{lat,jdbcType=DECIMAL},
            </