mybatis之XMLLanguageDriver使用方式例子

java直接获取MyBatis将要执行的动态sql命令(不是拦截器方式) 本文介绍了一种实现MyBatis动态SQL解析的方法,用于将配置在数据库中的SQL模板转换为最终可执行的SQL语句。通过使用MyBatis的XMLLanguageDriver类解析动态SQL,并结合参数替换逻辑,成功实现了包括foreach、if等动态标签的SQL解析。文章详细展示了从JSON参数到最终SQL的转换过程,提供了完整的Java实现代码。该方法解决了特殊需求场景下需要展示动态SQL执行结果的问题,为类似需求提供了参考解决方案。 阅读详情

mybatis中的XMLLanguageDriver类出现的一大原因在于:使用注解配置sql语句没有使用xml的方式灵活和强大,为了弥补这种缺陷,XMLLanguageDriver出现了。下面只是简单的举个例子,贴点代码,不多做解释。因为对于使用过mybatis的人,一看就明白。

SimpleSelectInLangDriver
package com.core.mybatis.languageDriver;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.Configuration;

//一次编写即可
public class SimpleSelectInLangDriver extends XMLLanguageDriver implements LanguageDriver {

    private static final Pattern inPattern = Pattern.compile("\\(#\\{(\\w+)\\}\\)");

    @Override
    public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {

        Matcher matcher = inPattern.matcher(script);
        if (matcher.find()) {
            script = matcher.replaceAll("<foreach collection=\"$1\" item=\"_item\" open=\"(\" "
                    + "separator=\",\" close=\")\" >#{_item}</foreach>");
        }

        script = "<script>" + script + "</script>";
        return super.createSqlSource(configuration, script, parameterType);
    }
}

SimpleUpdateLangDriver
package com.core.mybatis.languageDriver;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.Configuration;

public class SimpleUpdateLangDriver extends XMLLanguageDriver implements LanguageDriver{

    private final Pattern inPattern = Pattern.compile("\\(#\\{(\\w+)\\}\\)");

    @Override
    public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {
        Matcher matcher = inPattern.matcher(script);
        if (matcher.find()) {
            StringBuilder sb = new StringBuilder();
            sb.append("<set>");

            sb.append("<if test=\"name != null \">   name = #{name},</if>");
            sb.append("<if test=\"price != null \"> price = #{price},</if>");


         /*   for (Field field : parameterType.getDeclaredFields()) {
                String tmp = "<if test=\"_field != null\">_column=#{_field},</if>";
                sb.append(tmp.replaceAll("_field", field.getName()).replaceAll("_column",
                        CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName())));
            }*/

            sb.deleteCharAt(sb.lastIndexOf(","));
            sb.append("</set>");

            script = matcher.replaceAll(sb.toString());
            script = "<script>" + script + "</script>";
        }

        return super.createSqlSource(configuration, script, parameterType);
    }
}
BookDao是dao层

package com.springmvc.family.dao;

import java.util.List;

import org.apache.ibatis.annotations.Lang;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.core.mybatis.languageDriver.SimpleSelectInLangDriver;
import com.core.mybatis.languageDriver.SimpleUpdateLangDriver;
import com.springmvc.family.model.Book;

/**
 * @author lihong 2016年6月24日 下午2:12:19
 * @version v1.0
 */
@Mapper
public interface BookDao
{
    /**
     * @param book 
     * @author lihong 2016年6月24日 下午2:12:39
     * @since v1.0
     */
    public void addBook(Book book);

    /**
     * 与addBook功能相同,此处是为了测试两种插入数据并获取主键的方法
     * @param book void
     * @author lihong 2016年6月24日 下午2:58:33
     * @since v1.0
     */
    public void insert(Book book);

    /**
     * @return List<Book>
     * @author lihong 2016年6月24日 下午2:12:59
     * @since v1.0
     */
    public List<Book> getAll(Book book);


    @Select("SELECT * FROM book WHERE id IN (#{idList})")
    @Lang(SimpleSelectInLangDriver.class)
    List<Book> getBookByIdInBatch(@Param("idList") List<Integer> idList);


    @Update("UPDATE book (#{book}) WHERE id = #{id}")
    @Lang(SimpleUpdateLangDriver.class)
    void updateUsersById(Book book);

}
Book 类是实体类

@Alias("Book")
public class Book implements java.io.Serializable
{
    /**
     * @Fields serialVersionUID :
     */
    private static final long serialVersionUID = -8019185784560242092L;
    private int id;
    private String name;
    private float price;

    /**
     * @author lihong 2016年6月24日 下午2:11:59
     * @since v1.0
     */
    public Book()
    {

    }

    /**
     * @return the id
     */
    public int getId()
    {
        return id;
    }
    /**
     * @param id the id to set
     */
    public void setId(int id)
    {
        this.id = id;
    }
    /**
     * @return the name
     */
    public String getName()
    {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name)
    {
        this.name = name;
    }
    /**
     * @return the price
     */
    public float getPrice()
    {
        return price;
    }
    /**
     * @param price the price to set
     */
    public void setPrice(float price)
    {
        this.price = price;
    }





}
BookDaoTest 类是使用测试用例

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.springmvc.AnnotationServiceTest;
import com.springmvc.family.dao.BookDao;
import com.springmvc.family.model.Book;

/**
 * @author lihong 2016年6月24日 下午2:37:49
 * @version v1.0
 */
public class BookDaoTest extends AnnotationServiceTest
{

    @Autowired
    private BookDao bookDao;

    private Book getBook()
    {
        Book book = new Book();
        book.setName("测试生成的书名");
        book.setPrice(2.32f);
        return book;
    }

    /**
     * 测试插入数据后返回自增的主键id值
     * @author lihong 2016年6月24日 下午2:45:56
     * @since v1.0
     */
    @Test
    public void testAdd()
    {
        for(int i = 0; i < 10; i++)
        {
            Book book = getBook();
            bookDao.addBook(book);
            System.out.println("数据库自增主键策略返回的id是:  " + book.getId() + "         ");
        }

    }

    /**
     *  采用另外一种配置方式测试插入数据后返回自增的主键id值
     * @author lihong 2016年6月24日 下午3:02:09
     * @since v1.0
     */
    @Test
    public void testInsert()
    {
        for(int i = 0; i < 10; i++)
        {
            Book book = getBook();
            bookDao.insert(book);
            System.out.println("数据库自增主键策略返回的id是:  " + book.getId() + "         ");
        }

    }

    /**
     * @author lihong 2016年6月24日 下午2:49:51
     * @since v1.0
     */
    @Test
    public void testGetAll()
    {
        for(int i = 0; i < 4; i++) { //循环是为了验证是否有缓存,是否只是到数据库查询一次
            Book book = new Book();
            book.setName("测试生成的书名");
            book.setPrice(2.32f);

            List<Book> all = bookDao.getAll(book);
            for(Book bk : all)
            {
                System.out.print("id: " + bk.getId() + "  ");
                System.out.print("name: " + bk.getName() + "  ");
                System.out.print("price: " + bk.getPrice() + "  ");
                System.out.println("-----------------------------------------------------");
            }
        }
    }


    @Test
    public void testGetInBatchById() {

        List<Integer> idList = new ArrayList<Integer>();
        idList.add(24);
        idList.add(25);
        List<Book> books = bookDao.getBookByIdInBatch(idList);
        for(Book book : books)
        {
            System.out.print("id: " + book.getId() + "  ");
            System.out.print("name: " + book.getName() + "  ");
            System.out.print("price: " + book.getPrice() + "  ");
            System.out.println("-----------------------------------------------------");
        }

    }

    @Test
    public void testUpdateBookById() {
        Book book = new Book();
        book.setId(23);
        book.setName("***************");
        book.setPrice(2.32f);
        bookDao.updateUsersById(book);
    }


}
手敲Mybatis(七)-细化xml语句解析和构建 为什么这一章节要细分之前的解析xml处理逻辑,原因是违反了单一原则设计,职责并不明确,将Sql语句、参数、返回值等等一切都进行解析,那么这种的需要拆开,为了后面可维护可扩展,例如Mapper级别的有mapper解析,Sql语句有Sql语句的解析,因为Sql也是脚本,需要对脚本进行动态处理,也会延伸一些脚本类来处理对应语句图一,全部职责混到一个类里一个方法里。 阅读详情

相关推荐

手敲Mybatis(八)-参数处理器

在之前的章节里边,类PreparedStatementHandler我们还没有处理在执行Sql时的参数,目前是硬编码写死存储的,如:ps.setLong(),这里就只能处理long类型的数据因为写死了,我们需要处理下让它支持设置不同的数据类型。根据要求我们知道本次最重要的就是参数处理器,考虑下需要怎么解析XML中的参数并放到对应容器里,使用时调用参数处理器进行设置对应参数呢?这就是今天的主题。

dfBeautifulLive的博客 1288

Mybatis—LanguageDriver

LanguageDriver主要用于构造SqlSource和ParameterHandler,从LanguageDriver在Mybatis中调用链路来看,Configuration#newParameterHandler通过调用LanguageDriver#createParameterHandler完成构建ParameterHandler,通过调用LanguageDriver#createSqlSource来完成构建SqlSource。

乐只悠悠 1772

Mybatis系列七:XMLStatementBuilder创建MappedStatement

Mybatis系列七:XMLStatementBuilder创建MappedStatement 概述 在《Mybatis系列四:XMLMapperBuilder解析XL配置文件》一文【1.3.6 解析select|insert|update|delete元素】章节中,解析select|insert|update|delete元素时XMLStatementBuilder创建MappedStateme...

lemon 1624

mybatis+mybatisplus源码学习(十二)XMLLanguageDriver

目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 XMLLanguageDriver用于对sql脚本进行解析,解析各种标签。 提示:以下是本篇文章正文内容,下面案例可供参考 一、pandas是什么? (1) @Override public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) { // issue ..

码易的博客 917

MyBatis源码解析——动态SQL实现原理_mybatis注解动态sql provider(2)

如上面的代码所示,StaticSqlSource类的内容比较简单,只封装了Mapper解析后的SQL内容和Mapper参数映射信息。

2401_84436058的博客 1004

MyBatis内置XML元素解析器解析自定义标签——快速掌握MyBatis自定义标签开发

作为一个技术人员,一定要懂得把自己的知识通过有效的表达传递给他人。我认为把自己的知识通过文章的方式进行传播是非常有必要的。这也是技术博客文章的重要性。MyBatis 是 Apache 基金会的一个开源项目,它是一个优秀的持久层框架,可以用于 Java 的应用开发。MyBatis 提供了强大的映射工具,使得数据库操作变得简单而方便。MyBatis 在 MyBatis-Spring 中也提供了 Spring 和 MyBatis 之间的集成支持。

AI天才研究院 2378

Mybatis—解析SQL配置

Mybatis源代码中SqlSource描述XML文件或者Java注解配置的SQL信息,SqlNode描述动态SQL配置中的和等标签,LanguageDriver的职责就是负责将Mapper SQL配置进行解析,然后将SQL配置信息转换为SqlSource对象。从而可见LanguageDriver是解析SQL信息配置关键所在,即触发解析SQL信息配置的源头。

乐只悠悠 1465

NCCL 源码深度解析:从初始化到通信链路构建全流程

本文深入解析了NVIDIA Collective Communication Library (NCCL) 的核心工作机制,从通信组初始化、硬件拓扑发现,到P2P、共享内存及网络传输链路的构建。详细剖析了源码中集合通信任务的执行流程与Proxy线程的协同机制,为开发者进行高性能分布式训练的性能调优与深度问题排查提供了清晰的底层视角。

hp777的博客 551

Spring mybatis源码篇章-XMLLanguageDriver解析sql包装为SqlSource

前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-MybatisDAO文件解析(二) 前文主要分析了Spring中XML配置文件方式的加载MappedStatement,本文在前文的基础上简单了解下Mybatis的SQL语法并且看下CRUD节点是如何被解析的 mapper的动态sql语法 具体的动态sql的使用可在官网查看Mybatis 3 | ...

weixin_30865427的博客 524

项目回顾一:《高速多端口共享缓存模块》

本帖子仅为了回顾一下一年前自己动手完成的第一个数字ic设计项目的历程,为复试做一下准备,完成的这个sramc模块花了整整四个月的时间,从0到12个模块的代码产出以及模块的验证,虽然没有拿奖,也没有进入复赛,设计过程中使用的技术手段和算法也不太成熟,但这这是一个值得记录的过程!

weixin_60261760的博客 1258

ControlCAN.dll开发适配USBCAN_E/2E_U设备

摘要:本文提供了USBCAN_E/2E_U设备的配置指南:1)安装专用驱动;2)获取最新的ControlCAN.dll文件;3)修改VCI调用顺序,新增VCI_SetReference函数设置波特率;4)使用工具计算波特率配置值,并给出了常见波特率对应的代码参考值(如500K对应0x060007)。配置过程强调使用特定工具计算精确的波特率参数,并提供了相关软件下载链接。

weixin_43969033的博客 392

深入浅出Mybatis源码解析——SqlSource的创建流程

前言 在前一篇文章深入浅出Mybatis源码解析——映射文件加载流程中,最后说到了创建SqlSource和创建MappedStatement对象,由于篇幅原因最后只好终止了,所以便只好在写一篇文章来说说SqlSource这样的一个创建流程是怎样的,在本系列第一篇完成后,也曾问过一两个认识的读者,有说不太看得懂,可能本人写博客不够图文并茂,所以在下一篇博文中准备来整理一张Mybatis的一个完整的...

寒山道杳 995

S7-1200g2运动控制实战:从轴组配置到程序调试

本文详细介绍了S7-1200g2运动控制功能的实战应用,从轴组配置到程序调试的全流程。通过TIA Portal中的工艺对象配置,实现单轴、同步轴组等运动控制模型,并分享常见问题排查与性能优化经验,帮助工程师快速掌握中小型自动化设备的运动控制技术。

weixin_28698059的博客 591

sql server解析xml属性为表格_Mybatis中SqlSource解析流程详解

前面几篇文章都在详细分析mapper的加载过程,但是始终没有看到sql的解析过程,今天来详细分析下。解析sql的位置前面分析到不管是通过注解还是通过xml方式生成mapper,最终都是调用MapperBuilderAssistant类的addMappedStatement方法,这个方法接受的其中一个SqlSource参数,SqlSource类中就是XML文件或者注解方法中映射语句的实现。那么Sql...

weixin_39606799的博客 104

Cisco 路由器 打环测试教程

环 回测试是很常用的一种测试,通常用于检查和分析端口或线路问题。如下图所示,我们在设备端口上用命令loopback(某些端口上命令格式为 loopback diagnostic)使接口从内部将自己发送的信号转接到自己的接收端(如红线所示),通过检查数据发送和接收的情况来判断端口工作状态是否正常。如果 需要对端口进行完全的检测,可以使用符合标准的短跳线将端口收发短接构成环...

weixin_34304013的博客 2024

python 中心线提取_二值分析 | OpenCV + skimage如何提取中心线

点击上方蓝字关注我们微信公众号:OpenCV学堂关注获取更多计算机视觉与深度学习知识问题前几天有个人问了我一个问题,问题是这样的,他有如下的一张二值图像:怎么得到白色Blob中心线,他希望的效果如下:显然OpenCV中常见的轮廓分析无法获得上面的中心红色线段,本质上这个问题是如何提取二值对象的骨架,提取骨架的方法在OpenCV的扩展模块中,另外skimage包也支持图像的骨架提取。这里就...

weixin_42204453的博客 4290

【Mybatis源码分析】动态标签的底层原理,DynamicSqlSource源码分析

DynamicSqlSource 是用 DynamicContext 对象中的 sqlBuilder 对象进行动态Sql片段拼接的,它是一个StringJoiner对象,以空格分隔开片段。 解析映射xml中的动态sql标签是封装在SqlNode对象中,其中是通过 MixedSqlNode 混合 SqlNode 进行遍历,然后通过递归的一种形式进行处理的。 SqlSourceBuilder.parse 进行了sql 最后的处理,处理了#{},并对参数进行了封装。

qq_63691275的博客 2479

无人驾驶汽车系统入门(三十二)——FEC算法:点云快速欧几里得聚类实战解析

本文深入解析了FEC算法在无人驾驶点云聚类中的高效应用,通过逐点处理策略和体素栅格预分割技术,实现了比传统欧几里得聚类快百倍的速度。文章详细介绍了算法原理、Python实现及参数调优指南,并对比了FEC与传统算法的性能差异,为无人驾驶系统开发提供了实用解决方案。

weixin_29065015的博客 487

Mybatis中SqlSource解析流程详解

前面几篇文章都在详细分析mapper的加载过程,但是始终没有看到sql的解析过程,今天来详细分析下。 解析sql的位置 前面分析到不管是通过注解还是通过xml方式生成mapper,最终都是调用MapperBuilderAssistant类的addMappedStatement方法,这个方法接受的其中一个SqlSource参数,SqlSource类中就是XML文件或者注解方法中映射语句的实现。 那么SqlSource对象是在哪里创建的呢? 在通过注解实现mapper的流程中是在MapperAnnotation

IT乐知 499

五段式S型算法笔记

又因为有 v-v0= 0.5jt通式: 所以有 vm-v0= 0.5jtm 所以有4vm-4v0= 2jtm。算法1: v=2vm-v0-0.5*jt+2jt*tm-2jtm*tm。加加速度j 自己设置 已知,vmax自己设置已知;所以有4vm-4v0= 2jtm带入算法1。

qq_36658033的博客 683

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Mybatis源码学习(六)——sql 字符串获取及参数设置过程

从之前对 StatementHandler 类(Mybatis源码学习(五)——StatementHandler-优快云博客)的分析可发现 mybatis 使用 BoundSql 对象获取 sql 字符串,而 BoundSql 对象的获取则是使用 MappedStatement 参数的 getBoundSql 方法; getBoundSql 方法中首先调用 SqlSource 属性中的 getBoundSql 方法获取 BoundSql 对象,若 BoundSql 对象中的 paramete

weixin_63445802的博客 2005

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Mybatis动态sql语句的生成

在XMLLanguageDriver的createSQLSource()方法中,可以将已经经过解析的xml节点传入,并且传入相应的参数类型,开始动态sql语句的生成。 @Override public SqlSource createSqlSource(Configuration configuration, XNode script, Class&lt;?&gt; parameterType...

不说话装高手 2690

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Mybatis探索之XML与动态SQL

parsing包先从package org.apache.ibatis.parsing包说起TokenHandler接口public interface TokenHandler { String handleToken(String content); }只有一个方法,关于对字符串的处理。GenericTokenParser类GenericTokenParser类则是对Token处理的逻辑...

panxj856856的博客 470

Mybatis源码-SqlSource接口

SqlSource创建流程 入口:XMLLanguageDriver#createSqlSource @Override public SqlSource createSqlSource(Configuration configuration, XNodescript, Class<?> parameterType) { // 初始化了动态SQL标签处理器 XMLScriptBuilder builder = new XMLScriptBuilder(configuration, scrip

liujiaxing1995的博客 377
上一篇: 一个线程安全的计数器实现(java),可以让一个变量每天从1开始递增
下一篇: netty - HashedWheelTimer用法测试
lhever_
博客等级 码龄14年 213粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值