Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是MyBatis的核心。
使用#{}占位符,或者${}进行sql拼接
MyBatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
开发中通过使用pojo传递查询条件
查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其他查询条件,这是就需要使用包装对象传递输入参数。
包装对象:pojo类中的一个属性是另外一个pojo。
QueryVo.java
package com.nikehu.mybatis.pojo; /** * 包装的pojo * @author 猪猪 * */ public class QueryVo { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }UserMapper.xml
<!-- 包装的pojo --> <insert id="insertQueryVo" parameterType="QueryVo"> INSERT INTO `mybatis01`.`user` ( `username`, `birthday`, `sex`, `address` ) VALUES ( #{ user.username }, #{ user.birthday }, #{ user.sex }, #{ user.address } ) ; </insert>resultType可以指定成功查询结果映射为pojo,但需要pojo属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名做一个对应关系,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询
如果sql查询字段名和pojo的属性名不一致:
解决方案1:取别名
<select id="getOrderList" resultType="order"> SELECT `id`, `user_id` `userId`, `number`, `createtime`, `note` FROM `order` </select>解决方案2:resultMap解决字段名与属性不一致的问题
<!-- 定义resultMap --> <resultMap type="order" id="order_list_map"> <!-- <id/>用于映射主键 --> <id property="id" column="id"/> <!-- <result/> 用于映射其他字段 --> <result property="userId" column="user_id"/> <result property="number" column="number"/> <result property="createtime" column="createtime"/> <result property="note" column="note"/> </resultMap> <!-- 使用resultMap --> <select id="getOrderListMap" resultMap="order_list_map"> SELECT `id`, `user_id`, `number`, `createtime`, `note` FROM `order` </select>当pojo中部分属性名和数据库表中字段名一致时,可以不用配置,但是type属性必须写对,大小写不区分
使用where标签,就不能再手动的加上where关键字。
sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql复用的目的
<!-- 使用sql标签将重复的sql片段抽取出来 --> <sql id="user_sql"> `id`, `username`, `birthday`, `sex`, `address` </sql> <select id="getUserById" parameterType="int" resultType="user"> SELECT <include refid="user_sql"></include> FROM `mybatis01`.`user` WHERE id = #{id} </select> <select id="getUserByPojo" parameterType="user" resultType="user"> SELECT <!-- 使用include标签引入sql片段 --> <include refid="user_sql"></include> FROM `mybatis01`.`user` <!-- WHERE username LIKE #{name} --> <where> <if test="username != null and username != ''"> and username LIKE '%${username}%' </if> <if test="sex != null and sex != ''"> and sex = #{sex} </if> </where> </select>场景1:Sql 中in关键字的使用
<select id="getUsersByIds" parameterType="QueryVo" resultType="user"> SELECT <include refid="user_sql"/> `uuid2` FROM `user` <where> <!-- foreach循环标签的使用 id IN(1,25,29,30,40) collection:要遍历的集合; open:循环开始时加上的片段; close:循环结束时加上的片段; seseparator:每一次循环的分隔符; item:每一次循环的元素变量。 --> <foreach collection="ids" open="id IN(" item="uid" separator="," close=")"> #{uid} </foreach> </where> </select> package com.nikehu.mybatis.pojo; import java.util.List; /** * 包装的pojo * @author 猪猪 * */ public class QueryVo { private User user; private List<Integer> ids; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public List<Integer> getIds() { return ids; } public void setIds(List<Integer> ids) { this.ids = ids; } } @Test public void testGetUsersByIds(){ SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); QueryVo vo = new QueryVo(); ArrayList<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(2); ids.add(29); ids.add(30); ids.add(40); vo.setIds(ids); List<User> users = mapper.getUsersByIds(vo); for (User user : users) { System.out.println(user); } }简写:构建ids列表
vo.setIds(Arrays.asList(1,25,29,30,40));一个订单只能有一个用户
一个用户可以有多个用户
关联查询使用resultType必须要有与数据库关系一致的pojo
OrderMapper.xml
<!-- 一对一关联查询使用resultType 查询订单关联用户 --> <select id="getOrderUser" resultType="OrderUser"> SELECT o.`id`, o.`user_id` userId, o.`number`, o.`createtime`, o.`note`, u.`username`, u.`address` FROM `order` o LEFT JOIN `user` u ON u.`id` = o.`user_id` </select>OrderUser.java
package com.nikehu.mybatis.pojo; /** * 订单关联用户信息的pojo * @author 猪猪 * */ public class OrderUser extends Order { private String username; private String address; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "OrderUser [username=" + username + ", address=" + address + ", getId()=" + getId() + ", getUserId()=" + getUserId() + ", getNumber()=" + getNumber() + ", getCreatetime()=" + getCreatetime() + ", getNote()=" + getNote() + "]"; } }在Order类里面封装一个User类对象,在使用resultMap查询(更符合面向对象的思想)
Order.java
package com.nikehu.mybatis.pojo; /** * 订单关联用户信息的pojo * @author 猪猪 * */ public class OrderUser extends Order { private String username; private String address; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "OrderUser [username=" + username + ", address=" + address + ", getId()=" + getId() + ", getUserId()=" + getUserId() + ", getNumber()=" + getNumber() + ", getCreatetime()=" + getCreatetime() + ", getNote()=" + getNote() + "]"; } }OrderMapper.xml
<!-- 一对一关联查询使用resultMap 查询订单关联用户 --> <resultMap type="order" id="order_user_map"> <!-- <id/>用于映射主键 --> <id property="id" column="id"/> <!-- <result/> 用于映射其他字段 --> <result property="userId" column="user_id"/> <result property="number" column="number"/> <result property="createtime" column="createtime"/> <result property="note" column="note"/> <!-- user属性的映射 --> <!-- association用于配置一对一关系; property:order里面的user属性 javaType:指定property的Java类型,可以用别名 --> <association property="user" javaType="User"> <id column="user_id" property="id"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="username" property="username"/> <result column="address" property="address"/> </association> </resultMap> <select id="getOrderUserList" resultMap="order_user_map"> SELECT o.`id`, o.`user_id`, o.`number`, o.`createtime`, o.`note`, u.`sex`, u.`birthday`, u.`username`, u.`address` FROM `order` o LEFT JOIN `user` u ON u.`id` = o.`user_id` </select>User.java
package com.nikehu.mybatis.pojo; import java.util.Date; import java.util.List; public class User { private Integer id; private String username;// 用户姓名 private String sex;// 性别 private Date birthday;// 生日 private String address;// 地址 private String uuid2; private List<Order> orders; public List<Order> getOrders() { return orders; } public void setOrders(List<Order> orders) { this.orders = orders; } public String getUuid2() { return uuid2; } public void setUuid2(String uuid2) { this.uuid2 = uuid2; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address=" + address + ", uuid2=" + uuid2 + "]"; } } <resultMap type="user" id="user_order_map"> <id column="id" property="id"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> <result column="username" property="username"/> <result column="address" property="address"/> <result column="uuid2" property="uuid2"/> <!-- collection用于配置一对多关联 property:User中的订单列表orders属性; ofType:property值的Java类型,支持别名 --> <collection property="orders" ofType="Order"> <id property="id" column="oid"/> <!-- <result/> 用于映射其他字段 --> <result property="userId" column="id"/> <result property="number" column="number"/> <result property="createtime" column="createtime"/> <result property="note" column="note"/> </collection> </resultMap> <select id="getUserOrderMap" resultMap="user_order_map"> SELECT u.`id`, u.`username`, u.`birthday`, u.`sex`, u.`address`, u.`uuid2`, o.`id` oid, o.`number`, o.`createtime`, o.`note` FROM `user` u LEFT JOIN `order` o ON o.`user_id` = u.`id` </select> @Test public void testGetUserOrderMap() { SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> users = mapper.getUserOrderMap(); for (User user : users) { System.out.println(users); System.out.println("该用户的订单有:"); for (Order order : user.getOrders()) { System.out.println(order); } } sqlSession.close(); }多对多可拆分成两个一对多查询