MyBatis框架(6)动态sql
本次全部学习内容:MyBatisLearning
什么是动态sql:
mybatis的核心,对sql进行灵活的操作,通过对表达式的判断,对sql灵活的拼接
在之前小案例的基础上我们先进行简单的实现一下:
if:
在UserMapper.xml文件中找到:
<!-- 动态sql --> <!-- 综合查询 --> <select id="findBySelect" parameterType="com.MrChengs.po.UserView" resultType="com.MrChengs.po.UserCustomer" > select * from user <where> <if test="userCustomer!=null"> <if test="userCustomer.sex!=null and userCustomer.sex!='' "> and user.sex=#{userCustomer.sex} </if> <if test="userCustomer.username!=null and userCustomer.username!=''"> and user.username like '%${userCustomer.username}%' </if> </if> </where> </select>
注意:where标签可以自动去掉条件中的第一个 and
测试类:
//此时值传入username这一个值
//动态sql //高级查询 @Test public void testfindBySelect() throws Exception{ SqlSession sqlSession = getSqlSessionFactory().openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); UserView userView = new UserView(); UserCustomer userCustomer = new UserCustomer(); //userCustomer.setSex(1); userCustomer.setUsername("小明"); userView.setUserCustomer(userCustomer); List<User> user = mapper.findBySelect(userView); for(User u : user){ System.out.println(u); } sqlSession.close(); }
结果:
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@545997b1] DEBUG [main] - ==> Preparing: select * from user WHERE user.username like '%小明%' DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 3 User [id=16, username=张小明, birthday=null, sex=1, address=河南郑州] User [id=22, username=陈小明, birthday=null, sex=1, address=河南郑州] User [id=25, username=陈小明, birthday=null, sex=1, address=河南郑州]
在if中判断此时,之传入了一个username进行查询。
SQL片段:
把实现动态sql判断的代码块抽取出来,组成一个sql片段,在需要的时候可以直接引用,重用性高
定义一个sql片段,基于上面的代码进行测试和实践:
在UserMapper.xml文件中:
定义sql片段:
<!-- sql片段 --> <!-- id唯一,是sql片段的唯一标识 --> <!-- 基于单表定义sql片段,这样的话sql片段的可重用性才高,在sql片段中不要包括where --> <sql id="selectBySql"> <if test="userCustomer!=null"> <if test="userCustomer.sex!=null and userCustomer.sex!='' "> and user.sex=#{userCustomer.sex} </if> <if test="userCustomer.username!=null and userCustomer.username!=''"> and user.username like '%${userCustomer.username}%' </if> </if> </sql>
引用sql片段:
<!-- 动态sql --> <!-- 综合查询 --> <select id="findBySelect" parameterType="com.MrChengs.po.UserView" resultType="com.MrChengs.po.UserCustomer" > select * from user <where> <!-- 引用sql片段 --> <include refid="selectBySql"></include> </where> </select>
测试代码同上次测试代码!
foreach标签:
假设我们同时查询多个id
select from user where id = 1 or id = 10 or id = 12
在UserMapper.xml文件中,对之前的代码进行加工修改:
此时,在测试的时候,我只是测试foreach里面的内容,所以,对代码进行了修改
<!-- sql片段 --> <!-- id唯一,是sql片段的唯一标识 --> <!-- 基于单表定义sql片段,这样的话sql片段的可重用性才高,在sql片段中不要包括where --> <sql id="selectBySql"> <if test="userCustomer!=null"> <if test="userCustomer.sex!=null and userCustomer.sex!='' "> and user.sex=#{userCustomer.sex} </if> <if test="userCustomer.username!=null and userCustomer.username!=''"> and user.username like '%${userCustomer.username}%' </if> </if> <!-- foreach --> <!-- 测试 --> <!-- select from user where id = 1 or id = 10 or id = 12 --> <!-- collection:指定输入对象的集合 --> <!-- item:每个遍历生成成的对象 --> <!-- open:开始遍历时 拼接的串 --> <!-- close:结束遍历时 拼接的串 --> <!-- separator:遍历时两个对象中需要拼接的串 --> <foreach collection="ids" close=")" item="userId" open="1=1 and (" separator="or"> id=#{userId} </foreach> </sql> <!-- 动态sql --> <!-- 综合查询 --> <select id="findBySelect" parameterType="com.MrChengs.po.UserView" resultType="com.MrChengs.po.UserCustomer" > select * from user <where> <!-- 引用sql片段 --> <include refid="selectBySql"></include> </where> </select>
测试代码:
//foreach //动态sql //高级查询 @Test public void testfindBySelect() throws Exception{ SqlSession sqlSession = getSqlSessionFactory().openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); UserView userView = new UserView(); //foreach List<Integer> ids = new ArrayList<>(); ids.add(1); ids.add(2); ids.add(30); userView.setIds(ids); List<User> users = mapper.findBySelect(userView); for(User user : users){ System.out.println(user); } sqlSession.close(); }
结果:
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@545997b1] DEBUG [main] - ==> Preparing: select * from user WHERE 1=1 and ( id=? or id=? or id=? ) DEBUG [main] - ==> Parameters: 1(Integer), 2(Integer), 30(Integer) DEBUG [main] - <== Total: 2 User [id=1, username=王五, birthday=null, sex=2, address=null] User [id=30, username=Ma, birthday=null, sex=1, address=安徽]
对于
SELECT * FROM USER WHERE id IN(1,2,30)来说
只需要修改下面的测试代码,其余的测试代码均不变
<foreach collection="ids" close=")" item="userId" open="1=1 and id in(" separator=","> id=#{userId} </foreach>
sql只接收一个数组参数,这时sql解析参数的名称mybatis固定为array,如果数组是通过一个pojo传递到sql则参数的名称为pojo中的属性名。
index:为数组的下标。
item:为数组每个元素的名称,名称随意定义
open:循环开始
close:循环结束
separator:中间分隔输出