Mybatis最入门---动态查询(foreach)

本文,我们来介绍使用Mybatis提供的标签实现我们某些循环增改删差的需求。官方文档中的内容过于简陋,于是,博主筛选出比较全面讲述foreach用法的的内容,并且配有例子。希望各位看官能够手动敲一遍下面的例子,达到快速学习的目的。

 

准备工作:

 

a.操作系统 :win7 x64

b.基本软件:MySQL,Mybatis,SQLyog

--------------------------------------------------------------------------------------------------------------------------------------------------------

我们先来叙述中可以供我们使用的属性有哪些:

 

属性描述
item循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details。
具体说明:在list和数组中是其中的对象,在map中是value。
该参数为必选。
collection要做foreach的对象,作为入参时,List对象默认用list代替作为键,数组对象有array代替作为键,Map对象没有默认的键。
当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:
如果User有属性List ids。入参是User对象,那么这个collection = "ids"
如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id"
上面只是举例,具体collection等于什么,就看你想对那个元素做循环。
该参数为必选
separator元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
openforeach代码的开始符号,一般设置为“(“和close=")"合用。常用在in(),values()时。该参数可选。
closeforeach代码的关闭符号,一般设置为“)“和open="("合用。常用在in(),values()时。该参数可选。
index在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。【这个具体用法见下文】

 

--------------------------------------------------------------------------------------------------------------------------------------------------------

【本文我们将给出完整的工程代码,请读者一定在本地运行一遍,加深理解】

1.首先,创建我们的Spring09工程,工程结构图如下:

\

2.pom文件内容如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<dependencies>
         <dependency>
             <groupid>junit</groupid>
             junit</artifactid>
             <version>4.12</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupid>org.mybatis</groupid>
             mybatis</artifactid>
             <version>3.3.1</version>
         </dependency>
         <dependency>
             <groupid>mysql</groupid>
             mysql-connector-java</artifactid>
             <version>5.1.26</version>
         </dependency>
         <dependency>
             <groupid>log4j</groupid>
             log4j</artifactid>
             <version>1.2.17</version>
         </dependency>
     </dependencies>

3. 数据库 配置文件jdbc.properties内容如下:

 

 

?
1
2
3
4
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.username=root
jdbc. password =1234
4.日志配置文件log4j.properties内容如下:

 

 

?
1
2
3
4
log4j.rootLogger=debug,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
5.mybatis-config.xml配置文件内容如下:

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<! --?xml version="1.0" encoding="UTF-8" ?-->
 
<configuration>
     <properties resource= "jdbc.properties" >
     <settings>
         <setting name = "logImpl" value= "LOG4J" >
     </setting></settings>
     <typealiases>
         <package name = "com.csdn.ingo.entity" >
     </package></typealiases>
     <environments default = "development" >
         <environment id= "development" >
             <transactionmanager type= "JDBC" >
             <datasource type= "POOLED" >
                 <property name = "driver" value= "${jdbc.driverClassName}" >
                 <property name = "url" value= "${jdbc.url}" >
                 <property name = "username" value= "${jdbc.username}" >
                 <property name = "password" value= "${jdbc.password}" >
             </property></property></property></property></datasource>
         </transactionmanager></environment>
     </environments>
     <mappers>
           <mapper resource= "mappers/UserInfoMapper.xml" >
            <mapper resource= "mappers/UserMapper.xml" >
     </mapper></mapper></mappers>
     
</properties></configuration>
6.UserInfo.java文件内容如下:

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@SuppressWarnings( "serial" )
public class UserInfo implements Serializable {
     
     private String userid;
     private String department;
     private String position;
     private String mobile;
     private String gender;
     private String email;
     private Departments depart;
 
// set ,get,构造函数,toString,请自行补充
}
7.user.java文件内容如下:

 

 

?
1
2
3
4
5
6
@SuppressWarnings( "serial" )
public class User implements Serializable {
     
     private String id;
     private String password ;
// set ,get,构造函数,toString,请自行补充
}

 

?
1
 
8.SqlSessionFactoryUtil.java内容如下:

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.csdn.ingo.util;
 
import java.io.InputStream;
 
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 
public class SqlSessionFactoryUtil {
 
     private static SqlSessionFactory sqlSessionFactory;
     
     public static SqlSessionFactory getSqlSessionFactory(){
         if(sqlSessionFactory== null ){
             InputStream inputStream= null ;
             try{
                 inputStream=Resources.getResourceAsStream( "mybatis-config.xml" );
                 sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
             }catch(Exception e){
                 e.printStackTrace();
             }
         }
         return sqlSessionFactory;
     }
     
     public static SqlSession openSession(){
         return getSqlSessionFactory().openSession();
     }
}
--------------------------------------------------------------------------------------------------------------------------------

 

准备工作结束,马上开始我们的讲解,请睁大眼见哦!

--------------------------------------------------------------------------------------------------------------------------------

一.参数为数组Array。

1.UserTest的单元测试方法为:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
     public void testForEachArray() {
         try {
             String[] sa = new String[]{ "admin" , "customer" , "customer2" };
             UserInfoDao userInfo = sqlSession.getMapper(UserInfoDao.class);
             List<userinfo> UIList = userInfo.selectUserInfoByForEachArray(sa);
             for (UserInfo ui : UIList) {
                 System. out .println(ui.toString());
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
     }</userinfo>

 

【注意】

2.UserInfoDao.java的内容如下:【注意这里接口的形参为数组类型】

 

?
1
2
3
4
5
public interface UserInfoDao {
     
     List<userinfo> selectUserInfoByForEachArray(String[] sa);  
     
}</userinfo>
3.UserInfoMapper.xml的内容如下:

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<! --?xml version="1.0" encoding="UTF-8" ?-->
 
<mapper namespace= "com.csdn.ingo.dao.UserInfoDao" >
     <resultmap id= "UserInfoResult" type= "userInfo" >
         <id column = "userid" property= "userid" >
         <result column = "department" property= "department" >
         <result column = "position" property= "position" >
         <result column = "mobile" property= "mobile" >
         <result column = "gender" property= "gender" >
         <result column = "email" property= "email" >
     </result></result></result></result></result></id></resultmap>
< select id= "selectUserInfoByForEachArray" resultmap= "UserInfoResult" >
         select * from userinfo
         
             where userid in
             
                 #{item}
             
         
     </ select >
</mapper>

 

【解释】

a。这里的if标签能够判断出数组是否为空。但是没有判断出数组中的内容是否为空。即,当数组中有内容时或者数组为null时,该SQL语句能够正常执行,但是如果数组为空的话,if判断的结果为真,但foreach执行0次。这种情况下,Mybatis会组装出1条错误的sql语句。换句话说这里if是多余的。

b。这里collection属性配置为”array“

c。index在这条语句中未使用,所以是可以缺省的。移除也不会引起错误

d。open,close只会在开始与结尾出现一次。

e。separator会使用配置的”,“来每次间隔标签内的内容。

f。#{item}中的item必须与中的item属性的值”item“保持一致。

------------------------------

4.运行单元测试方法,应该能够看到如下输出:【各位看官可以自行变化数组内容,观察控制台输出】

\
-------------------------------------------------------------------------------------------------------------------------------------

二。参数为List

1.在UserTest中新增单元测试方法:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
     public void testForEachList() {
         try {
             List<string> userlist = new ArrayList<string>();
             userlist. add ( "admin" );
             userlist. add ( "customer" );
             userlist. add ( "customer2" );
             UserInfoDao userInfo = sqlSession.getMapper(UserInfoDao.class);
             List<userinfo> UIList = userInfo.selectUserInfoByForEachList(userlist);
             for (UserInfo ui : UIList) {
                 System. out .println(ui.toString());
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
     }</userinfo></string></string>
2.在UserInfoDao.java增加接口内容如下:
?
1
List<userinfo> selectUserInfoByForEachList(List<string> sl);</string></userinfo>
3.在UserInfoDaoMapper.xml中,增加如下内容:

 

 

?
1
2
3
4
5
6
7
8
9
< select id= "selectUserInfoByForEachList" resultmap= "UserInfoResult" >
         select * from userinfo
         
             where userid in
             
                 #{item}
             
         
     </ select >

 

【解释】

a.与上面类似:这里的if标签能够判断出List是否为空。但是没有判断出List中的内容是否为空。即,当List中有内容时或者List为null时,该SQL语句能够正常执行,但是如果List为空的话,if判断的结果为真,但foreach执行0次。这种情况下,Mybatis会组装出1条错误的sql语句。换句话说这里if是多余的。

 

b。这里collection属性配置为”list“

c。index在这条语句中未使用,所以是可以缺省的。移除也不会引起错误

d。其他内容请参考上面array中的解释

-------------------------------

4.运行单元测试方法,应该能够看到如下输出:【各位看官可以自行变化数组内容,观察控制台输出】
\
-------------------------------------------------------------------------------------------------------------------------------------

三。参数为Map

1.在UserTest中新增单元测试方法:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
     public void testForEachMap() {
         try {
             Map<string, object= "" > map = new HashMap<string, object= "" >();
             List<string> userlist = new ArrayList<string>();
             userlist. add ( "admin" );
             map.put( "userids" , userlist);
             UserInfoDao userInfo = sqlSession.getMapper(UserInfoDao.class);
             List<userinfo> UIList = userInfo.selectUserInfoByForEach(map);
             for (UserInfo ui : UIList) {
                 System. out .println(ui.toString());
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
     }</userinfo></string></string></string,></string,>
2.在UserInfoDao.java增加接口内容如下:

 

 

?
1
List<userinfo> selectUserInfoByForEach(Map<string,object> map);</string,object></userinfo>
3.在UserInfoDaoMapper.xml中,增加如下内容:

 

 

?
1
2
3
4
5
6
7
8
9
< select id= "selectUserInfoByForEach" parametertype= "Map" resultmap= "UserInfoResult" >
         select * from userinfo
         
             where userid in
             
                 #{ParamsId}
             
         
     </ select >

 

【解释】

a.与上面类似:这里的if标签能够判断出map中否包含userids这个key,其对应的value可以任意。但是没有判断出value中的内容是否为空。即,当value中有内容时或者key不存在时,该SQL语句能够正常执行,但是如果value为空的话,if判断的结果为真,但foreach执行0次。这种情况下,Mybatis会组装出1条错误的sql语句。换句话说这里if是多余的。

b.这里collection属性配置为map中list对应的key的值,而不是value或者”list“

c.各位看官请注意这里的#{ParamsId}是与属性item中的ParamsId对应的

----------------------------------

4.运行单元测试方法,应该能够看到如下输出:【各位看官可以自行变化数组内容,观察控制台输出】

\
-------------------------------------------------------------------------------------------------------------------------------------

四。特别的index

1.在UserTest中新增单元测试方法:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
     public void testForeachIndex() {
         try {
             Map<string, object= "" > map = new HashMap<string, object= "" >();
             Map<string,object> user =new HashMap<string, object= "" >();
             user .put( "1" , "aaa" );
             user .put( "2" , "bbb" );
             user .put( "3" , "ccc" );
             user .put( "4" , "ddd" );
             user .put( "5" , "eee" );
             map.put( "map" , user );
             UserDao userDao = sqlSession.getMapper(UserDao.class);
                         int re = userDao.insertUserByForEachIndex(map);
             if(re==1){
                 System. out .println( "success" );
             }
             sqlSession. commit ();
         } catch (Exception e) {
             e.printStackTrace();
         }
     }</string,></string,object></string,></string,>
2.在UserDao.java增加接口内容如下:
?
1
2
3
public interface UserDao {
     int insertUserByForEachIndex(Map<string,object> map);
}</string,object>
3.在UserDaoMapper.xml中,增加如下内容:
?
1
2
3
4
5
6
< insert id= "insertUserByForEachIndex" >
         insert into sysuser (id, password ) values
         <foreach close = "" collection= "map" index = "id" item= "item" open = "" separator= "," >
             (#{id},#{item})
         </foreach>
     </ insert >

 

【注释】

博主这里找了官方文档,其给出的解释是:当使用可迭代对象或者数组时,index是当前迭代的次数,item的值是本次迭代获取的元素。当使用字典(或者Map.Entry对象的集合)时,index是键,item是值。

这里我们又参考其他博文中给出的解释,设计上面的示例,供各位看官学习。

作为示例,请读者特别留心SQL语句中所诠释的官方文档的意思。即,index对应key,item对应value。

鉴于篇幅的关系,更多用法就请各位举一反三吧!

----------------------------------

4.运行单元测试方法,应该能够看到如下输出:
\

-------------------------------------------------------------------------------------------------------------------------------------

至此,Mybatis最入门---动态查询(foreach)结束

特别备注:

关于的用法需要具体应用场景和大量的练习,才能运用自如,请各位客官开心的敲代码吧!




http://www.2cto.com/database/201604/502331.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值