MyBatis-动态sql与高级映射
if标签一般应用在多条件查询中select idselectByMultipleCondition resultTypecar parameterTypeCar SELECT id, car_num AS carNum, brand, guide_price AS guidePrice, produce_time AS produceTime, car_type AS carType FROM t_car WHERE 11 /* if标签中test属性是必须的test属性的值是一个boolean类型的值。 只有test属性的值为true时if标签中的SQL片段才会被拼接到最终的SQL语句中。 test属性中可以使用的是 当使用了Param注解test使用的是注解指定的参数名。比如Param“brand”那么只能使用brand 若没有使用Param注解test使用的是arg0、arg1、param1、param2 当使用了Pojo那么test中使用的Pojo类的属性名*/ if testcarNum ! null and carNum ! AND car_num #{carNum} /if if testbrand ! null and brand ! AND brand #{brand} /if if testcarType ! null and carType ! AND car_type #{carType} /if /selectwhere标签where标签的作用让where子句更加动态智能所有条件都为空时where标签保证不会生成where子句自动去除某些条件前面多余的and或or(只能处理前面的不能处理后面的)select idselectByMultipleConditionWithWhere resultTypecar parameterTypeCar SELECT id, car_num AS carNum, brand, guide_price AS guidePrice, produce_time AS produceTime, car_type AS carType FROM t_car where if testcarNum ! null and carNum ! AND car_num #{carNum} /if if testbrand ! null and brand ! AND brand #{brand} /if if testcarType ! null and carType ! AND car_type #{carType} /if /where /selecttrim标签select idselectByMultipleConditionWithTrim resultTypecar parameterTypeCar SELECT id, car_num AS carNum, brand, guide_price AS guidePrice, produce_time AS produceTime, car_type AS carType FROM t_car /* prefix:加前缀 suffix:加后缀 prefixOverrides:去掉前缀 suffixOverrides:去掉后缀 prefixWHERE 表示在trim标签所有你内容的前面加上WHERE关键字。 suffixOverridesAND |OR 表示如果trim标签中的内容以AND或者OR结尾那么就去掉这个AND或者OR。 */ trim prefixWHERE suffixOverridesAND |OR if testcarNum ! null and carNum ! car_num #{carNum} AND /if if testbrand ! null and brand ! brand #{brand} AND /if if testcarType ! null and carType ! car_type #{carType} /if /trim /selectset标签主要使用在update语句当中用来生成set关键字同时去掉最后多余的“”比如我们只更新提交不为空的字段如果提交的数据是空或者“”那么不更新这个字段。update idupdateBySet parameterTypeCar UPDATE t_car set if testcarNum ! null and carNum ! car_num #{carNum}, /if if testbrand ! null and brand ! brand #{brand}, /if if testguidePrice ! null guide_price #{guidePrice}, /if if testproduceTime ! null produce_time #{produceTime}, /if if testcarType ! null and carType ! car_type #{carType} /if /set WHERE id #{id} /updatechoose when otherwise 标签这三个标签等同于 if... else if ... else ... 只有一个分支会被执行。select idselectByChoose resultMapcar select * from t_car where choose when testcarNum ! null and carNum ! car_num #{carNum} /when when testbrand ! null and brand ! brand #{brand} /when otherwise 11 /otherwise /choose /where /selectforeach标签循环数组或集合时使用批量删除!--对应的接口方法 int deleteByIds(Param(ids) Long[] ids);-- delete iddeleteByIds DELETE FROM t_car WHERE id IN /*collection:指定要遍历的集合可以是list、set、array等。 item:代表数组或集合中的元素 open:指定foreach标签生成的SQL片段的开头 separator:指定foreach标签生成的SQL片段之间的分隔符 close:指定foreach标签生成的SQL片段的结尾 这个foreach标签会将传入的list集合中的每个元素都用#{id}占位符替换并且用逗号分隔开来最终生成一个类似于(id1,id2,id3)这样的SQL片段。 这样就可以实现批量删除的功能了。 注意在使用foreach标签时传入的参数类型必须是一个集合类型否则会报错。*/ foreach collectionids itemid open( separator, close) #{id} /foreach /delete批量插入!--对应的接口方法 int insertBatch(Param(list) ListCar carList);-- insert idinsertBatch parameterTypelist INSERT INTO t_car (id, car_num, brand,guide_price,produce_time,car_type) VALUES foreach collectionlist itemcar separator, (null, #{car.carNum}, #{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType}) /foreach /insertsql标签和include标签sql标签用来声明sql片段。include标签用来将声明的sql片段包含到某个sql语句当中。主要为了代码复用。sql idcarColumns id, car_num AS carNum, brand, guide_price AS guidePrice, produce_time AS produceTime, car_type AS carType /sql select idselectAllCarWithSql resultTypecar SELECT include refidcarColumns/ FROM t_car /selectMyBatis的高级映射及延迟加载有一个业务场景有学生表和班级表。一个学生对应一个班级一个班级包含多个学生。那么学生与班级的关系就是多对一。多的一方是Student 、一的一方是Clazz。怎么分主表和子表原则谁在前谁就是主表。多对一多在前多就是主表一对多一在前一就是主表多对一多对一的映射方式包括三种一条sql语句级联属性映射一条sql语句association两条sql语句分步查询优点1.可复用2.支持懒加载第一种方式级联属性映射Student类设计如下添加一个班级类的属性表示学生关联的班级对象。public class Student { private Integer sid; private String sname; private Clazz clazz; // 班级对象 Override public String toString() { return Student{ sid sid , sname sname \ , clazz clazz }; } public Clazz getClazz() { return clazz; } public void setClazz(Clazz clazz) { this.clazz clazz; } public Student(Integer sid, String sname) { this.sid sid; this.sname sname; } public Student() { } public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname sname; } }StudentMapper.xml设计如下?xml version1.0 encodingUTF-8 ? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.ali.mapper.StudentMapper !--一条sql语句级联属性映射-- resultMap idstudentResultMap typeStudent id propertysid columnsid/ result propertysname columnsname/ result propertyclazz.cid columncid/ result propertyclazz.cname columncname/ /resultMap !--对应的Mapper接口方法是Student getStudentById(int id);-- select idgetStudentById resultMapstudentResultMap select s.sid, s.sname, c.cid, c.cname from t_student s left join t_clazz c on s.cid c.cid where s.sid #{sid} /select /mapper第二种方式一条sql语句associationPojo类不用修改只是resultMap内容做了修改StudentMapper.xml设计如下resultMap idstudentResultMapAssociation typeStudent id propertysid columnsid/ result propertysname columnsname/ !--association标签表示一对一的关系 property属性表示要映射的Pojo类的属性名Stusrnt类的clazz属性 javaType属性表示这个属性的类型 column属性表示要使用哪个列的值来查询关联对象-- association propertyclazz javaTypeClazz id propertycid columncid/ result propertycname columncname/ /association /resultMap !--对应的Mapper接口方法是Student getStudentById(int id);-- select idgetStudentById resultMapstudentResultMapAssociation select s.sid, s.sname, c.cid, c.cname from t_student s left join t_clazz c on s.cid c.cid where s.sid #{sid} /select第三种方式两条sql语句分步查询第一步查询StudentMapper.xml设计如下resultMap idstudentResultMapStep typeStudent id propertysid columnsid/ result propertysname columnsname/ !--association标签表示一对一的关系 property属性表示要映射的Pojo类的属性名Stusrnt类的clazz属性 column属性表示要使用哪个列的值来查询关联对象 select指定第二步sql语句的id-- association propertyclazz columncid selectcom.ali.mapper.ClazzMapper.getClazzByIdStep2/ /resultMap select idgetStudentByIdStep1 resultMapstudentResultMapStep select s.sid, s.sname, s.cid from t_student s where s.sid #{sid} /select第二步查询ClazzMapper.xml设计如下!--分步查询第二步根据cid获取班级信息-- select idgetClazzByIdStep2 resultTypeClazz select cid, cname from t_clazz where cid #{cid} /select这种方式执行了2次sql查询。多对一延迟加载分步查询的优点可复用性强。延迟加载的核心就是用的时候再查询不用的时候不查询。作用是提高性能。尽可能的不查或者少查。当查询返回student对象时此还没有执行第二步查询当调用student.getClazz()方法时才执行第二步查询。在mybatis当中怎么开启延迟加载在association标签种添加fetchTypelazy这是一种局部设置只针对当前的association关联的sql语句起作用。那怎么开启全局的懒加载呢在mybatis-config.xml文件中设置如下settings !--延迟加载的全局开关默认关闭。 所有的分步查询都采用延迟加载。 实际开发中建议开启。-- setting namelazyLoadingEnabled valuetrue/ /settings在开启全局延迟加载的情况下如果某个分步查询不需要开启延迟加载怎么办在对应的association标签中添加fetchTypeeager就可以关闭这个查询的延迟加载。一对多一个班级对应多个学生一对多的映射实现方式有两种collection分步查询第一种方式collection班级类设计如下public class Clazz { private Integer cid; private String cname; private ListStudent students; // 一个班级有多个学生 Override public String toString() { return Clazz{ cid cid , cname cname \ , students students }; } public ListStudent getStudents() { return students; } public void setStudents(ListStudent students) { this.students students; } public Clazz() { } public Clazz(Integer cid, String cname) { this.cid cid; this.cname cname; } public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname cname; } }ClazzMapper.xml文件设计如下resultMap idclazzResultMap typeClazz id propertycid columncid/ result propertycname columncname/ !--collection标签表示一对多的关系 property属性表示要映射的Pojo类的属性名Clazz类的students属性 ofType属性表示集合当中的元素类型-- collection propertystudents ofTypeStudent id propertysid columnsid/ result propertysname columnsname/ /collection /resultMap select idgetClazzByCollection resultMapclazzResultMap select cid, cname,s.sid, s.sname from t_clazz c left join t_student s on c.cid s.cid where c.cid #{cid} /select第二种方式分步查询第一步查询ClazzMapper.xml文件设计如下resultMap idclazzResultMapStep typeClazz id propertycid columncid/ result propertycname columncname/ !--collection标签表示一对多的关系 property属性表示要映射的Pojo类的属性名Clazz类的students属性 ofType属性表示集合当中的元素类型 columncid 表示根据cid查询学生信息-- collection propertystudents ofTypeStudent columncid selectcom.ali.mapper.StudentMapper.getStudentsByClazzId/ /resultMap select idgetClazzByIdStep1 resultMapclazzResultMapStep select cid, cname from t_clazz where cid #{cid} /select第二步查询StudentMapper.xml设计如下select idgetStudentsByClazzIdStep2 resultTypestudent select sid, sname from t_student where cid #{cid} /select