Mybatis中的输入输出映射
输入映射 -- 输入的参数类型:
1.简单类型 (略)
2.简单的pojo类型(类类型)(略)
3.自定义包装类型:
从前面的mapper接口的方法中可以看出来,每个方法都只能够传递一个参数,而且确实只能传一个参数。但是有些时候我们在关联查询的时候,可能查询条件有用户的信息还有商品的信息甚至还有订单的信息。那么这个时候,我们只能将所有的查询信息封装到一个对象中,然后使用这个对象作为输入参数。
举例:
查询: 根据用户的姓名和性别查询用户的信息
步骤:
1.定义用户扩展类
public class UserCustomer extends User {
private Double weight;
}
2.定义一个自定义的包装类,封装所有的查询条件
/**
* 自定义包装类, 封装所有的查询条件
* Author menglanyingfei
* Created on 2018.01.20 16:27
*/
public class QueryVo {
// 封装用户信息
private UserCustomer userCustomer;
// 封装商品信息
// private Items items;
public UserCustomer getUserCustomer() {
return userCustomer;
}
public void setUserCustomer(UserCustomer userCustomer) {
this.userCustomer = userCustomer;
}
}
3.定义接口中的方法
/**
* mapper开发的接口
* Created by menglanyingfei on 2018/1/20.
*/
public interface UserMapper {
// 根据用户的姓名和性别查询用户的信息, 采用包装类型作为输入参数
List findUserByNameAndSex(QueryVo queryVo);
}
4.编写映射文件(注意, 这里的输入输出类型都采用了类型别名)
5.测试代码
@Test
public void findUserBySexAndUsername() {
// 获取SqlSession
SqlSession session = factory.openSession();
// 通过SqlSession对象得到Mapper接口的一个代理对象
// 需要传递的参数是Mapper接口的类型
UserMapper userMapper = session.getMapper(UserMapper.class);
// 构建输入参数QueryVo
QueryVo queryVo = new QueryVo();
// 创建UserCustomer对象作为queryVo的属性
UserCustomer userCustomer = new UserCustomer();
userCustomer.setUsername("小");
userCustomer.setSex("1");
// 将UserCustomer对象设置到QueryVo中
queryVo.setUserCustomer(userCustomer);
// 通过代理对象调用UserMapper中的方法
List userList = userMapper.findUserByNameAndSex(queryVo);
System.out.println(userList);
// 红色标识!
System.err.println(userMapper);
// 关闭资源
session.close();
}
输入映射为HashMap类型
查询:根据用户的姓名和性别查询用户的信息, 使用HashMap作为输入参数类型
接口中的方法:
List findUserByHashMap(HashMap hashMap);
映射文件:
测试代码:
@Test
public void findUserByHashMap() {
// 获取SqlSession
SqlSession session = factory.openSession();
// 通过SqlSession对象得到Mapper接口的一个代理对象
// 需要传递的参数是Mapper接口的类型
UserMapper userMapper = session.getMapper(UserMapper.class);
// 创建HashMap对象
HashMap map = new HashMap<>();
map.put("sex", "1");
map.put("username1", "小");
// 通过代理对象调用UserMapper中的方法
List userList = userMapper.findUserByHashMap(map);
System.err.println(userList);
System.out.println(map.get("username1"));
// 关闭资源
session.close();
}
输出映射
ResultType关键字的使用
输出简单类型
根据用户名和性别统计一共有多少个这样的用户
映射文件的编写
接口中的方法:
public interface UserMapper {
// 根据姓名和性别统计人数, 采用QueryVo作为输入参数
Integer findUserCount(QueryVo queryVo);
}
测试代码:
public class UserMapperTest {
private SqlSessionFactory factory;
@Before
public void getFactory() throws Exception {
this.factory = new SqlSessionFactoryBuilder().build(
Resources.getResourceAsStream("mybatis/sqlMapConfig.xml")
);
}
@Test
public void findUserCount() {
SqlSession session = factory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
QueryVo queryVo = new QueryVo();
UserCustomer userCustomer = new UserCustomer();
userCustomer.setSex("1");
userCustomer.setUsername("小");
queryVo.setUserCustomer(userCustomer);
Integer count = userMapper.findUserCount(queryVo);
System.out.println(count);
// System.err.println(userMapper);
session.close();
}
}
ResultType输出HashMap
将一条查询记录的字段名作为map的key,字段值作为map的value 进行输出
根据id查询用户:
接口:
// 根据id查询用户, 采用HashMap作为输出映射
HashMap findUserById(Integer id);
映射文件:
测试代码:
@Test
public void findUserById() {
SqlSession session = factory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
HashMap map = userMapper.findUserById(28);
System.out.println(map);
session.close();
}
ResultType的小结
只有当数据库中查询出来的字段名和pojo中的set方法的方法名的后面一截相同的时候才能够将该字段的值成功的映射到该对象中。如果不同则不能映射成功。
如果查询出来的字段名和pojo中的set方法的方法名的后面一截没有一个相同的,那么这个时候连对象都没有,那么如何解决这个问题: 使用ResultMap 来完成映射关系
ResultMap的使用
根据id查询用户, 采用ResultMap 进行输出
映射文件:
接口:
// 根据id查询用户, 采用ResultMap作为输出类型
User findUserByResultMap(Integer id);
测试代码:
@Test
public void findUserByResultMap() {
SqlSession session = factory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.findUserByResultMap(28);
System.out.println(user);
session.close();
}
动态sql
Mybatis中提供了
和
来进行sql片段的拼接 ,满足不同的需求.
根据性别和姓名查询用户信息,如果没有输入查询条件那么将会查询所有信息
sql片段
将多条sql中公共的部分抽取出来, 定义一个sql片段, 然后可以在其他地方引入该sql片段,但是要注意, 如果引入是其他映射文件中的sql片段,那么在sql片段的id前面要加上命名空间
定义sql片段
and username like '%${userCustomer.username}%'
and sex = #{userCustomer.sex}
引入sql片段
映射文件:
查询用户名中带狗字, 性别为1, id为28或者40的用户信息
QueryVo中封装一个ids集合属性, 用来传递多个id值
/**
* 自定义包装类, 封装所有的查询条件
* Author menglanyingfei
* Created on 2018.01.20 16:27
*/
public class QueryVo {
// 封装用户信息
private UserCustomer userCustomer;
private List ids;
public List getIds() {
return ids;
}
public void setIds(List ids) {
this.ids = ids;
}
public UserCustomer getUserCustomer() {
return userCustomer;
}
public void setUserCustomer(UserCustomer userCustomer) {
this.userCustomer = userCustomer;
}
}
映射文件的编写:
Mybatis的高级映射
一对一映射
查询订单信息,并且关联查询出该订单对应的用户的姓名,性别,地址
这个过程中存在着 订单 ---> 用户 的一对一关系
通过观察发现结果集中既有订单的信息,也有用户的信息,所以我们可以定义一个类封装了所有的查询字段。然后采用该类型作为输出类型。
实体类:
public class OrdersCustomer extends Orders {
// 封装用户信息
private String username;
private String sex;
private String address;
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 String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
映射文件的编写:
接口中方法编写:
// 查询订单信息, 并且查询该订单对应的用户部分信息
List findOrdersAndUser();
测试代码:
public class OrdersMapperTest {
private SqlSessionFactory factory;
@Before
public void getFactory() throws Exception {
this.factory = new SqlSessionFactoryBuilder().build(
Resources.getResourceAsStream("mybatis/sqlMapConfig.xml")
);
}
// 查询订单信息, 并且查询该订单对应的用户部分信息
@Test
public void findOrdersAndUser() {
SqlSession session = factory.openSession();
OrdersMapper ordersMapper = session.getMapper(OrdersMapper.class);
List ordersCustomerList = ordersMapper.findOrdersAndUser();
for (OrdersCustomer oc : ordersCustomerList) {
System.out.println(oc.getUsername() + " -- " + oc.getSex() + " -- "
+ oc.getAddress());
}
session.close();
}
}
使用ResultMap 实现一对一映射
此时我们可以在Orders类中直接对用户信息进行封装,直接可以封装一个User对象
public class Orders {
private Integer id;
private Integer user_id;
private Integer number;
private Date createtime;
private String note;
// 封装用户信息
private User user;
// ...
}
映射文件的编写:
接口中方法定义:
// 查询订单信息, 并且查询该订单对应的用户部分信息, 采用ResultMap作为输出参数类型
List findOrdersAndUserByResultMap();
测试代码:
// 查询订单信息, 并且查询该订单对应的用户部分信息, 采用ResultMap作为输出参数
@Test
public void findOrdersAndUserByResultMap() {
SqlSession session = factory.openSession();
OrdersMapper ordersMapper = session.getMapper(OrdersMapper.class);
List ordersList = ordersMapper.findOrdersAndUserByResultMap();
System.out.println(ordersList);
session.close();
}
一对多映射
分析订单表和订单明细表:
Orderdetail(orders_id) ------->关联------>orders(id)
Orders(user_id) ----->关联----->user(id)
orders---->orderdetail : 一对多的关系
orderdetail----->orders : 一对一的关系
查询订单信息并且关联查询用户信息和对应的订单明细的信息
实体类:
public class Orders {
private Integer id;
private Integer user_id;
private Integer number;
private Date createtime;
private String note;
// 封装用户信息
private User user;
// 封装订单明细的信息
private List odlist;
// ...
}
映射文件:
接口中的方法:
// 查询订单信息并且关联用户信息和对应的订单明细的信息
List findOrdersAndUserAndOrderdetail();
多对多映射
查询用户信息并且关联查询用户购买的商品的信息
通过查看表结构我们知道 用户表和商品表在数据库的结构上面没有任何直接关联
通过ResultMap进行输出
用户-->订单 一对多
订单-->订单明细 一对多
订单明细-->商品 一对一
实现过程:
1.在User类中 有一个List
2.在Orders类型 有一个List
3.在Orderdetail类中 有一个Items items
实体类:
public class Items {
private Integer id;
private String name;
private Double price;
private String detail;
private String pic;
private Date createtime;
// ...
}
public class Orderdetail {
private Integer id;
private Integer orders_id;
private Integer items_id;
private Integer items_num;
// 一个订单明细包括一个商品
private Items items;
// ...
}
public class Orders {
private Integer id;
private Integer user_id;
private Integer number;
private Date createtime;
private String note;
// 封装用户信息
private User user;
// 封装订单明细的信息
private List odlist;
// ...
}
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 一个用户包括多个订单
List ordersList;
// ...
}
映射文件:
接口中方法定义:
// 查询用户信息并且关联查询用户购买的商品的信息
List findUserToItems();
测试代码:
// 查询用户信息并且关联查询用户购买的商品的信息
@Test
public void findUserToItems() {
SqlSession session = factory.openSession();
OrdersMapper ordersMapper = session.getMapper(OrdersMapper.class);
List userList = ordersMapper.findUserToItems();
System.out.println(userList.size());
session.close();
}
完整代码地址:(含SQL脚本)
https://github.com/menglanyingfei/SSMLearning/tree/master/mybatis_day03