单表查询
resultType与resultMap
- pojo包下实体类User ```java package com.tedu.DbDemo.pojo;
public class User { Integer userId; String username; String password; //它们的set,get方法,不展示了,占位置 }
- User表中,此时数据操作结果集user_id 和 pojo包下实体类userId不一致,其它属性username,password一致
- mapper包下接口UserMapper
```java
package com.tedu.DbDemo.mapper;
public interface UserMapper {
public List<User> select1();
public List<User> select2();
}
- mapper包下与接口对应的UserMapper.xml ```xml <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN” “http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<select id="select2" resultMap="map1">
select user_id,username,password from user
</select>
- controller层UserController类
```java
package com.tedu.DbDemo.controller;
@RestController
public class UserController {
@Autowired
UserMapper userMapper;
@RequestMapping("/select1")
public List<User> select1(){
return userMapper.select1();
}
@RequestMapping("/select2")
public List<User> select2(){
return userMapper.select2();
}
}
结论
只有两种association(一对一)、collection(一对多),表现很简洁
-
多表查询,表与表之间一对一关系
一个订单对应一个用户
- pojo包下实体类订单表Order、用户表User ```java package com.tedu.DbDemo.pojo;
public class Order { Integer orderId; Integer total; User user; //注意还有一个 user属性,这是关键 //它们的set,get方法,不展示了,占位置 }
- mapper包下接口OrderMapper
```java
package com.tedu.DbDemo.mapper;
public interface OrderMapper {
public Order selectById(Integer orderId);
}
mapper包下与接口对应的OrderMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.tedu.DbDemo.mapper.OrderMapper"> <resultMap type="com.tedu.DbDemo.pojo.Order" id="map2"> <result column="order_id" property="orderId"/> <result column="total" property="total"/> <!-- 结果集里面还要有user表的信息,映射到User类,采用标签association表示一对一 property表示结果子集合的类型(表名),javaType表示它对应的实体类 --> <association property="user" javaType="com.tedu.DbDemo.pojo.User"> <result column="user_id" property="userId"/> <result column="username" property="username"/> </association> </resultMap> <!-- select放的是sql语句 #{}是占位符--> <select id="selectById" resultMap="map2" parameterType="Integer"> SELECT order_id,total,jt_order.user_id,username FROM jt_order ,USER WHERE jt_order.order_id=#{orderId} AND user.user_id=jt_order.user_id </select> </mapper>
controller层OrderController类 ```java package com.tedu.DbDemo.controller;
@RestController public class OrderController { @Autowired OrderMapper orderMapper; @RequestMapping(“/selectOrderId”) public Order selectOneToOne() { Order order = orderMapper.selectById(1); return order; } }
- association标签、对象中含有一个对象属性 表示一对一
<a name="mcucy"></a>
### 多表查询,表与表之间多对多关系
- 一种商品分类对应多个商品
- pojo包下实体类商品分类表Category、商品表Item
```java
package com.tedu.DbDemo.pojo;
import java.util.List;
public class Category {
Integer categoryId;
String categoryName;
List<Item> itemList;
//注意还有一个 List<Item>属性,集合这是关键
//它们的set,get方法,不展示了,占位置
}
- mapper包下接口CategoryMapper ```java package com.tedu.DbDemo.mapper;
public interface CategoryMapper { public Category selectById(Integer categoryId); }
- mapper包下与接口对应的CategoryMapper.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tedu.DbDemo.mapper.CategoryMapper">
<resultMap type="com.tedu.DbDemo.pojo.Category" id="map1">
<result column="category_Id" property="categoryId"/>
<result column="category_Name" property="categoryName"/>
<!--一对一用assiocation 一对多是collection
collection里面 property是集合的名字,ofType是集合每个数据的接口.类名
-->
<collection property="itemList" ofType="com.tedu.DbDemo.pojo.Item">
<result column="item_name" property="itemName"/>
</collection>
</resultMap>
<!--
resultType 单表
resultMap 多表
parameterType 参数简单
paremeterMap 参数复杂
-->
<select id="selectById" resultMap="map1" parameterType="Integer">
SELECT category.category_id,category_name,item_name
FROM category,item
WHERE category.category_id=#{categoryId}
AND item.category_id=category.category_id
</select>
</mapper>
- 注意这里的sql语句,加入参数用#{},#{}封装了jdbc的PreparedStatement,能有效的防治sql注入问题,工作中也不用${},用#{}
- controller层CategoryController类 ```java package com.tedu.DbDemo.controller;
@RestController public class CategoryController {
@Autowired
CategoryMapper categoryMapper;
@RequestMapping("/category")
public Category selectOneToAll() {
Category category = categoryMapper.selectById(1);
return category;
}
}
- collection标签,对象中有一个对象集合属性,表示 一对多
<a name="TZbhu"></a>
## 高级查询
1. 高级查询中的where 条件 and like条件
1. in查询
- pojo包下实体类商品表Item
```java
package com.tedu.DbDemo.pojo;
public class Item {
Integer itemId;
String itemName;
Integer categoryId;
//它们的set,get方法,不展示了,占位置
}
- mapper包下接口ItemMapper ```java package com.tedu.DbDemo.mapper;
public interface ItemMapper {
//参数item中可以包含categoryId,itemName
//如果item中的某个属性值不为空,就根据这个属性值查找,where and语句
public List
//根据商品编号,in子查询
public List<Item> selectByList(List<Integer> list);
}
- mapper包下与接口对应的ItemMapper.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tedu.DbDemo.mapper.ItemMapper">
<!-- list<Item> select1() 如果方法返回的是集合,resultType的值是集合中元素的数据类型
parameterType是参数的类型
参数item中有categroryId,itemName属性 -->
<select id="select1" resultType="com.tedu.DbDemo.pojo.Item" parameterType="com.tedu.DbDemo.pojo.Item">
SELECT category_id categoryId
,item_name itemName
FROM item
<!-- 当直接写where
不传参数 生成的sql是from item where
前面的参数不传 ,sql是from item where and item_name like,出现错误
解决方法是把where改成标签<where>
-->
<where>
<if test="categoryId != null">
<!-- category_id是列名 , categoryId是传入参数item中的属性 -->
category_id=#{categoryId}
</if>
<if test="itemName != null">
<!-- concat是mysql内置的函数,拼接字符串 -->
and item_name like concat('%',#{itemName},'%')
</if>
</where>
</select>
<!-- 这里给列名设置了别名,列名和属性名相同,不再需要用resultMap映射 -->
<select id="selectByList" resultType="com.tedu.DbDemo.pojo.Item" parameterType="Integer">
SELECT item_id itemId,
category_id categoryId,
item_name itemName
FROM item
WHERE item_id IN
<!-- foreach 遍历集合 collection指定集合名称
item指定从集合取出的数据放在 id 中,id就是for循环的 i
open separator close的值就是in查询中的 ( , , , )
-->
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
</mapper>
- controller层ItemController类 ```java package com.tedu.DbDemo.controller;
@RestController public class ItemController { @Autowired ItemMapper itemMapper;
//模拟高级搜索中多个条件
//where and like查询
@RequestMapping("/item/Where")
public List<Item> selectWhere(Item item){
List<Item> listList = itemMapper.select1(item);
return listList;
}
//模拟用户的复选框选中多个值
//in查询
@RequestMapping("/item/selectIn")
public List<Item> selectIn(){
//模拟用户输入复选框 第 2,3,4 个
List<Integer> list = new ArrayList<Integer>();
list.add(2);
list.add(3);
list.add(4);
List<Item> itemList = itemMapper.selectByList(list);
return itemList;
}
}
<a name="E0EAl"></a>
## 扩展
<a name="6DvY5"></a>
### <sql><include>
- 可以在配置文件中调用的地方都进行include引用
```xml
<sql id="cols">id,name,birthday,address</sql>
refid引用上面的sql语句
<select id="list" resultType="user"> select <include refid="cols"/> from user </select>
SQL中有特殊字符
当SQL中有特殊字符,mybatis不能正常解析时,用CDATA括起来就解决了
如 <=不能正常解析:
<![CDATA[ and age<=#{age} ]]>
总结
首先根据业务需求写出sql语句,sql语句告诉你需要用到哪些表,哪些实体类
- 建立controller、mapper、pojo包
- pojo包下建立实体类
- 根据业务设定mapper包下接口
- 与接口对应的xml
- namespace为xml对应的 包名.类名
- 列名与实体类属性相等,直接用resultType作为返回类型,否则需要用resultMap将列名和实体类属性映射
- 返回值类型为 包名.类名
- 配置application.yml
- 两处填写的地址都是接口的包名
- 包扫描注解@mapperScan(“接口包名”)
- 告诉框架给这个变量一个对象
- 执行对像方法后,首先是找到接口方法
- 每个接口都对应一个同名的xml,xml中的namespace的值是接口的包名.类名,sql语句的id和接口方法名相同,执行接口方法,就会执行方法名对应id的sql语句。
- mapper.xml中定义的每个sql 的parameterType的类型和Mapper接口方法的输入参数类型一样
- 当数据库操作的结果集与实体类的属性名相同时,mapper.xml中使用resultType作为结果集的类型,且resultType的类型和Mapper接口方法的输出参数类型和一样,不相同或者多表时时,用resultMap映射,让结果集和实体类连在一起
- 最后以实体类的形式返回,框架调用jackson框架将对象转换为json返回