最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis?Plus使用XML編寫動態(tài)sql的超簡易方法

 更新時間:2022年01月20日 14:51:25   作者:MadlifeZhou  
這篇文章主要介紹了Mybatis?Plus使用XML編寫動態(tài)sql的超簡易方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

使用xml編寫動態(tài)sql

在Resources文件夾下創(chuàng)建一個Mapper文件夾

比如我們需要在User表中使用增刪改查,創(chuàng)建UserMapper.xml,對應(yīng)MybatisPlus中的UserMapper接口

image-20200721212245437

之后我們在application.yml中配置mapper文件夾的路徑

mybatis-plus:
? mapper-locations: classpath:mapper/*.xml

之后在UserMapper中創(chuàng)建函數(shù)

@Repository
public interface UserMapper extends BaseMapper<User> {
?? ??? ?// 使函數(shù)參數(shù)對應(yīng)xml中的參數(shù)wxNickName
? ? List<User> selectByName(@Param("wxNickName") String name);
}

就可以在UserMapper.xml中寫sql語句了

寫法和Mybatis一樣滴

<?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.zhou.usercenter.dao.user.UserMapper">
? ? <select id="selectByName" resultType="com.zhou.usercenter.domain.entity.user.User">
? ? ? ? select * from user
? ? ? ? <where>
? ? ? ? ? ? <if test="wxNickName != null and wxNickName != ''">
? ? ? ? ? ? ? ? wx_nickname like CONCAT('%',#{wxNickName},'%');
? ? ? ? ? ? </if>
? ? ? ? </where>
? ? </select>
</mapper>

之后調(diào)用即可

@SpringBootTest
class UserCenterApplicationTests {
? ? @Autowired
? ? UserMapper userMapper;
? ? @Test
? ? void contextLoads() {
? ? ? ? List<User> users = userMapper.selectByName("杰倫");
? ? ? ? System.out.println(users);
? ? }
}

即可看到正確的輸出結(jié)果 

image-20200721212300373

動態(tài)SQL語句的原理

Mybatis-Plus(簡稱MP)是一個 Mybatis 的增強工具,那么它是怎么增強的呢?其實就是它已經(jīng)封裝好了一些crud方法,開發(fā)就不需要再寫xml了,直接調(diào)用這些方法就行,就類似于JPA。那么這篇文章就來閱讀以下MP的具體實現(xiàn),看看是怎樣實現(xiàn)這些增強的。

入口類:MybatisSqlSessionFactoryBuilder

通過在入口類 MybatisSqlSessionFactoryBuilder#build方法中, 在應(yīng)用啟動時, 將mybatis plus(簡稱MP)自定義的動態(tài)配置xml文件注入到Mybatis中。

public class MybatisSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
    public SqlSessionFactory build(Configuration configuration) {
            // ... 省略若干行 
            if (globalConfig.isEnableSqlRunner()) {
                new SqlRunnerInjector().inject(configuration);
            }
            // ... 省略若干行 
            return sqlSessionFactory;
        }
}

這里涉及到2個MP2個功能類

擴展繼承自Mybatis的MybatisConfiguration類: MP動態(tài)腳本構(gòu)建,注冊,及其它邏輯判斷。

SqlRunnerInjector: MP默認插入一些動態(tài)方法的xml 腳本方法。

MybatisConfiguration類

這里我們重點剖析MybatisConfiguration類,在MybatisConfiguration中,MP初始化了其自身的MybatisMapperRegistry,而MybatisMapperRegistry是MP加載自定義的SQL方法的注冊器。

MybatisConfiguration中很多方法是使用MybatisMapperRegistry進行重寫實現(xiàn)

其中有3個重載方法addMapper實現(xiàn)了注冊MP動態(tài)腳本的功能。

public class MybatisConfiguration extends Configuration {
    /**
     * Mapper 注冊
     */
    protected final MybatisMapperRegistry mybatisMapperRegistry = new MybatisMapperRegistry(this);
    // ....
 
    /**
     * 初始化調(diào)用
     */
    public MybatisConfiguration() {
        super();
        this.mapUnderscoreToCamelCase = true;
        languageRegistry.setDefaultDriverClass(MybatisXMLLanguageDriver.class);
    }
 
    /**
     * MybatisPlus 加載 SQL 順序:
     * <p> 1、加載 XML中的 SQL </p>
     * <p> 2、加載 SqlProvider 中的 SQL </p>
     * <p> 3、XmlSql 與 SqlProvider不能包含相同的 SQL </p>
     * <p>調(diào)整后的 SQL優(yōu)先級:XmlSql > sqlProvider > CurdSql </p>
     */
    @Override
    public void addMappedStatement(MappedStatement ms) {
        // ...
    }
    
    // ... 省略若干行 
    /**
     * 使用自己的 MybatisMapperRegistry
     */
    @Override
    public <T> void addMapper(Class<T> type) {
        mybatisMapperRegistry.addMapper(type);
    }
    // .... 省略若干行 
}

在MybatisMapperRegistry中,MP將mybatis的MapperAnnotationBuilder替換為MP自己的MybatisMapperAnnotationBuilder

public class MybatisMapperRegistry extends MapperRegistry {
    @Override
    public <T> void addMapper(Class<T> type) {
        // ... 省略若干行 
        MybatisMapperAnnotationBuilder parser = new MybatisMapperAnnotationBuilder(config, type);
        parser.parse();
        // ... 省略若干行 
    }
}

在MybatisMapperRegistry類的addMapper方法中,真正進入到MP的核心類MybatisMapperAnnotationBuilder,MybatisMapperAnnotationBuilder這個類是MP實現(xiàn)動態(tài)腳本的關(guān)鍵類。

MybatisMapperAnnotationBuilder動態(tài)構(gòu)造

在MP的核心類MybatisMapperAnnotationBuilder的parser方法中,MP逐一遍歷要加載的Mapper類,加載的方法包括下面幾個

public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
    @Override
    public void parse() {
        //... 省略若干行 
        for (Method method : type.getMethods()) {
            /** for循環(huán)代碼, MP判斷method方法是否是@Select @Insert等mybatis注解方法**/
            parseStatement(method);
            InterceptorIgnoreHelper.initSqlParserInfoCache(cache, mapperName, method);
            SqlParserHelper.initSqlParserInfoCache(mapperName, method);
        }
        /** 這2行代碼, MP注入默認的方法列表**/
        if (GlobalConfigUtils.isSupperMapperChildren(configuration, type)) {
            GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant, type);
        }
        //... 省略若干行 
    }
 
    @Override
    public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
        Class<?> modelClass = extractModelClass(mapperClass);
        //... 省略若干行 
        List<AbstractMethod> methodList = this.getMethodList(mapperClass);
        TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
        // 循環(huán)注入自定義方法
        methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
        mapperRegistryCache.add(className);
    }
}
public class DefaultSqlInjector extends AbstractSqlInjector { 
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        return Stream.of(
            new Insert(),
            //... 省略若干行 
            new SelectPage()
        ).collect(toList());
    }
}

在MybatisMapperAnnotationBuilder中,MP真正將框架自定義的動態(tài)SQL語句注冊到Mybatis引擎中。而AbstractMethod則履行了具體方法的SQL語句構(gòu)造。

具體的AbstractMethod實例類,構(gòu)造具體的方法SQL語句

以 SelectById 這個類為例說明下

/**
 * 根據(jù)ID 查詢一條數(shù)據(jù)
 */
public class SelectById extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        /** 定義 mybatis xml method id, 對應(yīng) <id="xyz"> **/
        SqlMethod sqlMethod = SqlMethod.SELECT_BY_ID;
        /** 構(gòu)造id對應(yīng)的具體xml片段 **/
        SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(),
            sqlSelectColumns(tableInfo, false),
            tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),
            tableInfo.getLogicDeleteSql(true, true)), Object.class);
        /** 將xml method方法添加到mybatis的MappedStatement中 **/
        return this.addSelectMappedStatementForTable(mapperClass, getMethod(sqlMethod), sqlSource, tableInfo);
    }
}

至此,MP完成了在啟動時加載自定義的方法xml配置的過程,后面的就是mybatis ${變量} #{變量}的動態(tài)替換和預編譯,已經(jīng)進入mybatis自有功能。

小結(jié)一下

MP總共改寫和替換了mybatis的十多個類,主要如下圖所示:

總體上來說,MP實現(xiàn)mybatis的增強,手段略顯繁瑣和不夠直觀,其實根據(jù)MybatisMapperAnnotationBuilder構(gòu)造出自定義方法的xml文件,將其轉(zhuǎn)換為mybatis的Resource資源,可以只繼承重寫一個Mybatis類:SqlSessionFactoryBean 比如如下:

public class YourSqlSessionFactoryBean extends SqlSessionFactoryBean implements ApplicationContextAware { 
    private Resource[] mapperLocations; 
    @Override
    public void setMapperLocations(Resource... mapperLocations) {
        super.setMapperLocations(mapperLocations);
        /** 暫存使用mybatis原生定義的mapper xml文件路徑**/
        this.mapperLocations = mapperLocations;
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        /** 只需要通過將自定義的方法構(gòu)造成xml resource和原生定義的Resource一起注入到mybatis中即可, 這樣就可以實現(xiàn)MP的自定義動態(tài)SQL和原生SQL的共生關(guān)系**/
        this.setMapperLocations(InjectMapper.getMapperResource(this.dbType, beanFactory, this.mapperLocations));
        super.afterPropertiesSet();
    }
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • springboot集成Deepseek4j的項目實踐

    springboot集成Deepseek4j的項目實踐

    本文主要介紹了springboot集成Deepseek4j的項目實踐,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-03-03
  • 一篇文章幫你搞懂什么是java的進程和線程

    一篇文章幫你搞懂什么是java的進程和線程

    這篇文章主要介紹了java 線程詳解及線程與進程的區(qū)別的相關(guān)資料,網(wǎng)上關(guān)于java 線程的資料很多,對于進程的資料很是,這里就整理下,需要的朋友可以參考下
    2021-08-08
  • tk.Mybatis 插入數(shù)據(jù)獲取Id問題

    tk.Mybatis 插入數(shù)據(jù)獲取Id問題

    本文主要介紹了tk.Mybatis 插入數(shù)據(jù)獲取Id問題,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 實例詳解Java調(diào)用第三方接口方法

    實例詳解Java調(diào)用第三方接口方法

    很多項目都會封裝規(guī)定好本身項目的接口規(guī)范,所以大多數(shù)需要去調(diào)用對方提供的接口或第三方接口(短信、天氣等),下面這篇文章主要給大家介紹了關(guān)于Java調(diào)用第三方接口方法的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • Java調(diào)用elasticsearch本地代碼的操作方法

    Java調(diào)用elasticsearch本地代碼的操作方法

    這篇文章主要介紹了Java調(diào)用elasticsearch本地代碼的操作方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Java SSM框架如何添加寫日志功能

    Java SSM框架如何添加寫日志功能

    這篇文章主要介紹了Java SSM框架如何添加寫日志功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • java Struts2框架下實現(xiàn)文件上傳功能

    java Struts2框架下實現(xiàn)文件上傳功能

    這篇文章主要為大家詳細介紹了java Struts2框架下實現(xiàn)文件上傳功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • 程序包org.springframework不存在的解決辦法

    程序包org.springframework不存在的解決辦法

    這篇文章主要介紹了程序包org.springframework不存在的解決辦法,在使用IDEA創(chuàng)建SpringBoot項目時,剛打開無法正常運行,本文通過圖文結(jié)合的方式給大家介紹的非常詳細,具有一定參考價值,需要的朋友可以參考下
    2024-07-07
  • 詳解Spring MVC事務(wù)配置

    詳解Spring MVC事務(wù)配置

    這篇文章主要介紹了詳解Spring MVC事務(wù)配置,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • Maven配置文件settings.xml的實現(xiàn)

    Maven配置文件settings.xml的實現(xiàn)

    Maven是一個用于構(gòu)建和管理Java項目的強大工具,它依賴于設(shè)置文件來配置和管理其行為,其中最重要的之一便是settings.xml文件,本文主要介紹了Maven配置文件settings.xml的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2024-01-01

最新評論

辽源市| 武宣县| 万源市| 龙井市| 黄大仙区| 大余县| 丁青县| 宣武区| 太仆寺旗| 洞头县| 新乡县| 东明县| 黄石市| 徐闻县| 淮滨县| 南和县| 西宁市| 龙州县| 天长市| 万安县| 镇沅| 会泽县| 新丰县| 甘泉县| 开江县| 新密市| 甘孜| 恩平市| 阿坝| 巴彦淖尔市| 南雄市| 滦平县| 惠安县| 新宾| 平湖市| 武陟县| 年辖:市辖区| 施甸县| 兴义市| 平安县| 石屏县|