临汾建设局网站,上海行业门户网站建设应用,阿里云网站建设怎么样,广东东远建设工程管理有限公司网站MyBatis的动态SQL 1、if标签的用法2、choose标签的用法3、where标签4、set标签5、trim的用法6、foreach标签7、bind标签 使用过JDBC或者是其他的ORM框架的开发者都知道#xff0c;在很多操作中都需要去根据具体的条件进行SQL语句的拼接#xff0c;并且在有些时候一些标点符号… MyBatis的动态SQL 1、if标签的用法2、choose标签的用法3、where标签4、set标签5、trim的用法6、foreach标签7、bind标签 使用过JDBC或者是其他的ORM框架的开发者都知道在很多操作中都需要去根据具体的条件进行SQL语句的拼接并且在有些时候一些标点符号、空格之类的东西会导致开发工作很难去进行。而MyBatis的动态SQL就为了解决这样的问题应用而生的。 在MyBatis3版本之前使用动态的SQL需要使用非常多的标签并且非常麻烦。但是随着MyBatis的不断发展它提供了强大的OGNLObject-Graph Navigation Language表达式语言用着种语言来消除多余的标签。那么下面我们就来看看MyBatis提供的标签有哪些。 1、if标签的用法
if标签常被用在where语句中用来判断某个参数值是否满足条件。当然后来随着越来越多的应用它也会被用于update语句用来判断某个字段是否被更新或者是在insert语句中用来判断某个字段是否有值要插入。
假设现在有一个多条件查询的功能需要开发这些条件都是需要组合查询的。遇到这样的需求的时候就需要我们去编写一个SQL来完成条件的查询。那么这个时候问题来了对于组合查询来讲有些字段需要模糊查询、有些字段需要精准匹配。按照传统的写法代码如下。
select idtest resultTypecom.demo.bean.Userselect id , name ,age, address from user where name like concat(%,#{username},%) and age #{age}
/select 这个时候执行这个语句只有当我们同时输入了name和age两个参数的时候这个SQL才会被正确的执行。如果单纯的只提供一个参数的时候这个SQL就得不到我们想要的结果。这个时候我们就可以将上面的查询进行修改。
select idtest resultTypecom.demo.bean.Userselect id , name ,age, address from user where 11if testname!null and name!and name like concat(%,#{username},%) /ifif testage!null and age!and age #{age}/if
/select 这个时候当我们执行这条语句的时候如果name参数不传的话那么OGNL表达式就会判断是否为空如果表达式为true那么就会将对应的条件语句拼接到SQL中如果为false则不会将条件语句进行拼接。
这里需要注意的就是在使用if标签的时候它有一个test的属性是用来编写OGNL表达式的并且这个表达式可以支持任意字段的判断而且判断条件只限于String类型的字段值是否存在当有多个条件需要判断的时候可以用and或者是or进行连接
当然上面提到的在update、insert语句中的使用方式也是类似的。
2、choose标签的用法
上面我们介绍了关于if标签的用法但是if标签的用法中并没有提供一个if……else……类似的用法那么如果想要实现这种逻辑操作那么就需要用到 choose when otherwise标签了。
在一个choose标签中包含了两个子标签 when 和 otherwise 并且一个choose中至少有一个when可以有0个或者1个otherwise。 例如在有些场景中有这样的操作使用用户名、手机号、身份证号查询这个时候就需要将这三个条件进行组合进行查询。也许这里会有人说直接使用or语句进行连接不就可以了么当然这样也是可以的。如果说是要优先使用用户名查询、其次是手机号、最后是身份证号。这样的需求如何来编写这个SQL呢 select idtest resultTypecom.demo.bean.Userselect id , name ,age, address from user where 11choosewhen testname!null and name!and name like concat(%,#{username},%) /whenwhen testage!null and age!and age #{age}/whenotherwiseand 12/otherwise /choose
/select 需要注意的是在使用这个逻辑语句的时候一定要 保证逻辑的紧密性不然就会出现严重的SQL错误。在上面这个查询中如果otherwise没有限制的话那么所有满足条件的用户都会被查询出来。那么这个时候就会导致返回多条用户信息但是在接收参数中只接受一条用户信息的情况出现。但是如果我们加上了条件之后就会导致用户查询不到的情况发生无论如何查询都无法查询到用户。
3、where标签
首先where标签的作用就是如果这个标签中存在返回值那么就会插入一个where条件语句如果where后面的字符串是and或者是or开头的那么就会将其剔除。这样的话上面的标签就可以写成如下的样子。
select idtest resultTypecom.demo.bean.Userselect id , name ,age, address from user whereif testname!null and name!and name like concat(%,#{username},%) /ifif testage!null and age!and age #{age}/if/where
/select 这个时候当where条件中的if没有一个满足的时候where标签中就没有内容所以按照上面的说法where标签就不会出现在查询语句中也就不会出现条件不匹配的问题。如果if标签中有满足条件的语句那么where条件会自动的将这些条件进行拼接然后使用。这样我们就不需要再使用where 11 这样的操作了。
4、set标签
set标签的作用就是如果这标签中包含了对应的返回值那么就会插入一个set如果后面是逗号结尾就会剔除这个逗号。使用如下
update idtestupdate user setif testname!null and name!name #{username}, /ifif testage!null and age!age #{age},/ifid #{id}/setwhere id #{id}
/update 在set标签的用法中SQL后面的逗号会自动剔除但是如果set标签中没有满足条件的内容照样也会出现问题。为了避免这样的问题出现对于update语句中的条件一定要出现根据某个条件进行更新操作并且在更新的时候对应的值应该是不需要进行判断默认就是被传入的。
5、trim的用法 与where和set标签一样trim标签可以代替where和set来完成对应的操作其底层实现就是通过TrimSqlNode来实现。 trim标签有如下的属性
prefix 内容增加prefix前缀prefixOverrides把内容前缀字符去掉suffix增加后缀suffixOverrides取消后缀
6、foreach标签 foreach 标签主要用在构建 in 条件中它可以在 SQL 语句中迭代一个集合。 foreach 标签的属性主要有 item、index、collection、open、separator、close。 item 表示集合中每一个元素进行迭代时的别名。index 指定一个名字用于表示在迭代过程中每次迭代到的位置。open 表示该语句以什么开始。separator 表示在每次进行迭代之间以什么符号作为分隔符。close 表示以什么结束。
在使用 元素时最关键、最容易出错的是 collection 属性该属性是必选的但在不同情况下该属性的值是不一样的主要有以下 3 种情况
如果传入的是单参数且参数类型是一个 Listcollection 属性值为 list。如果传入的是单参数且参数类型是一个 array 数组collection 的属性值为 array。如果传入的参数是多个需要把它们封装成一个 Map当然单参数也可以封装成 Map。Map 的 key 是参数名collection 属性值是传入的 List 或 array 对象在自己封装的 Map 中的 key。
接下来针对上述三种情况进行演示
1单参数且参数类型是List
在IStudentDao添加方法。 ListStudent forEachTest1(ListInteger list);在studentMapper.xml中添加sql映射语句。 select idforEachTest1 resultTypecom.day1.entity.Studentselect * from t_student where age inforeach collectionlist indexindex itemitem open( separator, close)#{item}/foreach/select进行测试。 Testpublic void testForEach01() throws IOException {//1、读取配置文件InputStream in Resources.getResourceAsStream(SqlMapperConfig.xml);//2、创建SqlSessionFactory工厂SqlSessionFactoryBuilder builder new SqlSessionFactoryBuilder();SqlSessionFactory factory builder.build(in);//3、使用工厂生产SqlSession对象SqlSession sqlSession factory.openSession();//4、使用SqlSession创建dao接口的代理对象IStudentDao studentDao sqlSession.getMapper(IStudentDao.class);//5、使用代理对象执行方案ListInteger list new ArrayList();list.add(21);list.add(43);list.add(19);ListStudent students studentDao.forEachTest1(list);for(Student stu : students){System.out.println(stu);}//6、释放资源sqlSession.close();in.close();}2单参数且参数类型是array
在IStudentDao添加方法。 ListStudent forEachTest2(int[] ages);在studentMapper.xml中添加sql映射语句。
select idforEachTest2 resultTypecom.day1.entity.Studentselect * from t_student where age inforeach collectionarray indexindex itemitem open( separator, close)#{item}/foreach/select进行测试。 Testpublic void testForEach02() throws IOException {//1、读取配置文件InputStream in Resources.getResourceAsStream(SqlMapperConfig.xml);//2、创建SqlSessionFactory工厂SqlSessionFactoryBuilder builder new SqlSessionFactoryBuilder();SqlSessionFactory factory builder.build(in);//3、使用工厂生产SqlSession对象SqlSession sqlSession factory.openSession();//4、使用SqlSession创建dao接口的代理对象IStudentDao studentDao sqlSession.getMapper(IStudentDao.class);//5、使用代理对象执行方案int[] ages new int[]{19, 56};ListStudent students studentDao.forEachTest2(ages);for(Student stu : students){System.out.println(stu);}//6、释放资源sqlSession.close();in.close();}3封装map
在IStudentDao添加方法。 ListStudent forEachTest3(MapString, Object map);在studentMapper.xml中添加sql映射语句。
select idforEachTest3 resultTypecom.day1.entity.Studentselect * from t_student where age #{age} or address inforeach collectionlocations indexindex itemitem open( separator, close)#{item}/foreach/select进行测试。 Testpublic void testForEach03() throws IOException {//1、读取配置文件InputStream in Resources.getResourceAsStream(SqlMapperConfig.xml);//2、创建SqlSessionFactory工厂SqlSessionFactoryBuilder builder new SqlSessionFactoryBuilder();SqlSessionFactory factory builder.build(in);//3、使用工厂生产SqlSession对象SqlSession sqlSession factory.openSession();//4、使用SqlSession创建dao接口的代理对象IStudentDao studentDao sqlSession.getMapper(IStudentDao.class);//5、使用代理对象执行方案ListString locations new ArrayList();locations.add(北京);locations.add(河北);locations.add(安徽);MapString, Object map new HashMap();map.put(age, 30);map.put(locations, locations);ListStudent students studentDao.forEachTest3(map);for(Student stu : students){System.out.println(stu);}//6、释放资源sqlSession.close();in.close();}7、bind标签
通常在进行模糊查询时如果使用“${}”拼接字符串则无法防止 SQL 注入问题。如果使用字符串拼接函数或连接符号但不同数据库的拼接函数或连接符号不同MySQL 用的是的 concat 函数、Oracle 则是连接符号“||”这样 SQL 映射文件就需要根据不同的数据库提供不同的实现显然比较麻烦且不利于代码的移植。MyBatis 提供了 元素来解决这一问题。
bind标签可以使用OGNL表达式创建一个变量并将其绑定到上下文中。标签的两个属性都是必选项name 为绑定到上下文的变量名value 为 OGNL 表达式。
1在IStudentDao添加方法。 ListStudent testBind(Student student);2在studentMapper.xml中添加sql映射语句。
!--使用bind元素进行模糊查询--select idtestBind resultTypecom.day1.entity.Student parameterType com.day1.entity.Student!-- bind 中的 username 是 com.day1.entity.Student 的属性名--bind nameusername value% username %/select * from t_student where username like #{username}/select3进行测试。 Testpublic void testBind() throws IOException {//1、读取配置文件InputStream in Resources.getResourceAsStream(SqlMapperConfig.xml);//2、创建SqlSessionFactory工厂SqlSessionFactoryBuilder builder new SqlSessionFactoryBuilder();SqlSessionFactory factory builder.build(in);//3、使用工厂生产SqlSession对象SqlSession sqlSession factory.openSession();//4、使用SqlSession创建dao接口的代理对象IStudentDao studentDao sqlSession.getMapper(IStudentDao.class);//5、使用代理对象执行方案Student student new Student();student.setUsername(王);ListStudent students studentDao.testBind(student);for(Student stu : students){System.out.println(stu);}//6、释放资源sqlSession.close();in.close();}