输入映射
一、单个参数
方案1
public List<XXBean> getXXBeanList(@param("id")String id);
<select id="getXXXBeanList" parameterType="java.lang.String" resultType="XXBean">
select t.* from tableName t where t.id= #{id}
</select>
其中方法名和ID一致,#{}中的参数名与方法中的参数名一致, 这里采用的是@Param这个参数,实际上@Param这个最后会被Mabatis封装为map类型的。
select 后的字段列表要和bean中的属性名一致, 如果不一致的可以用 as 来补充。
方案2
//在实际需求中,我们经常需要结合多个条件综合查询,而这些条件并不在同一个POJO类中,
//所以需要对POJO类进行包装,生成另外一个类作为参数类型
public class UserQueryVO {
// 用户信息
private User user;
// 订单信息
private Order order;
//...
}
public List<User> getUserList(UserQueryVO vo);
<!--使用包装POJO类作为参数,查询用户列表 -->
<select id="getUserList" parameterType="com.zyj.mybatis.po.UserQueryVO" resultType="com.zyj.mybatis.po.User">
select * from user where username like '%${user.username}%' and sex = #{user.sex}
</select>
二、多个参数
方案1
public List<XXXBean> getXXXBeanList(String xxId, String xxCode);
<select id="getXXXBeanList" resultType="XXBean">不需要写parameterType参数
select t.* from tableName where id = #{0} and name = #{1}
</select>
由于是多参数那么就不能使用parameterType, 改用#{index}是第几个就用第几个的索引,索引从0开始
方案2
public List<XXXBean> getXXXBeanList(@Param("id")String id, @Param("code")String code);
<select id="getXXXBeanList" resultType="XXBean">
select t.* from tableName where id = #{id} and name = #{code}
</select>
由于是多参数那么就不能使用parameterType, 这里用@Param来指定哪一个
三、Map封装多参数:
public List<XXXBean> getXXXBeanList(HashMap map);
<select id="getXXXBeanList" parameterType="hashmap" resultType="XXBean">
select 字段... from XXX where id=#{xxId} code = #{xxCode}
</select>
其中hashmap是mybatis自己配置好的直接使用就行。map中key的名字是那个就在#{}使用那个
四、List封装in:
public List<XXXBean> getXXXBeanList(List<String> list);
<select id="getXXXBeanList" parameterType="list" resultType="XXBean">
select 字段... from XXX where id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach 最后的效果是select 字段... from XXX where id in ('1','2','3','4')
注意:如果parameterType是List或者Array的话,那么foreach语句中,collection属性值需要固定为list或者array。
五、selectList()只能传递一个参数,但实际所需参数既要包含String类型,又要包含List类型时的处理方法:
将参数放入Map,再取出Map中的List遍历。如下:
List<String> list_3 = new ArrayList<String>();
Map<String, Object> map2 = new HashMap<String, Object>();
list.add("1");
list.add("2");
map.put("list", list); //网址id
map.put("siteTag", "0");//网址类型
public List<SysWeb> getSysInfo(Map<String, Object> map2) {
return getSqlSession().selectList("sysweb.getSysInfo", map2);
}
<select id="getSysInfo" parameterType="java.util.Map" resultType="SysWeb">
select t.sysSiteId, t.siteName, t1.mzNum as siteTagNum, t1.mzName as siteTag, t.url, t.iconPath
from TD_WEB_SYSSITE t
left join TD_MZ_MZDY t1 on t1.mzNum = t.siteTag and t1.mzType = 10
WHERE t.siteTag = #{siteTag }
and t.sysSiteId not in
<foreach collection="list" item="item" index="index" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
输出映射基础之单表查询
输出映射有两种方式
1. resultType
2. resultMap
resultType
1.使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
2.如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。
3.只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。
输出简单类型
mapper.xml
<!-- 用户信息综合查询总数
parameterType:指定输入类型和findUserList一样
resultType:输出结果类型
-->
<select id="findUserCount" parameterType="com.iot.mybatis.po.UserQueryVo" resultType="int">
SELECT count(*) FROM user WHERE user.sex=#{userCustom.sex} AND user.username LIKE '%${userCustom.username}%'
</select>
mapper.java
//用户信息综合查询总数
@Test
public void testFindUserCount() throws Exception {
//......
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//创建包装对象,设置查询条件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
userCustom.setSex("1");
userCustom.setUsername("小");
userQueryVo.setUserCustom(userCustom);
//调用userMapper的方法
int count = userMapper.findUserCount(userQueryVo);
//......
}
小结
查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。
输出pojo对象和pojo列表
不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的。
在mapper.java指定的方法返回值类型不一样:
输出单个pojo对象,方法返回值是单个对象类型
//根据id查询用户信息
public User findUserById(int id) throws Exception;
输出pojo对象list,方法返回值是List
//根据用户名列查询用户列表
public List<User> findUserByName(String name) throws Exception;
生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用)还是selectList (返回集合对象调用 ).
resultMap
mybatis中使用resultMap完成高级输出结果映射。(一对多,多对多)
resultMap使用方法
如果查询出来的列名和pojo的属性名不一致,则需要通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
1.定义resultMap
2.使用resultMap作为statement的输出映射类型
定义reusltMap
<!-- 定义resultMap
将SELECT id id_,username username_ FROM USER 和User类中的属性作一个映射关系
type:resultMap最终映射的java对象类型,可以使用别名
id:对resultMap的唯一标识
-->
<resultMap type="user" id="userResultMap">
<!-- id表示查询结果集中唯一标识
column:查询出来的列名
property:type指定的pojo类型中的属性名
最终resultMap对column和property作一个映射关系 (对应关系)
-->
<id column="id_" property="id"/>
<!--
result:对普通名映射定义
column:查询出来的列名
property:type指定的pojo类型中的属性名
最终resultMap对column和property作一个映射关系 (对应关系)
-->
<result column="username_" property="username"/>
</resultMap>
使用resultMap作为statement的输出映射类型
<!-- 使用resultMap进行输出映射
resultMap:指定定义的resultMap的id,如果这个resultMap在其它的mapper文件,前边需要加namespace
-->
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
SELECT id id_,username username_ FROM USER WHERE id=#{value}
</select>
mapper.java
//根据id查询用户信息,使用resultMap输出
public User findUserByIdResultMap(int id) throws Exception;
测试代码
@Test
public void testFindUserByIdResultMap() throws Exception {
//......
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用userMapper的方法
User user = userMapper.findUserByIdResultMap(1);
//.......
}
小结
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
输出映射进阶之关联查询
场景:一个订单对应一个用户,同时一个订单对应多个订单明细
数据库
一对一(订单为主)
需求:查询订单列表,关联查询用户信息
sql语句:
SELECT orders.*, user.`username`, user.`sex` FROM orders, USER WHERE orders.`user_id` = user.`id`
方式一:resultType
由于订单pojo类orders中没有含有用户表user字段,所以这里可以包装订单类orders
public class OrdersExt extends Orders {
private String username;
private String sex;
//省略getter和setter方法
}
// mapper接口
public interface OrdersMapper {
public List<OrdersExt> findOrdersAndUserByRstType();
}
// mapper映射文件
<mapper namespace="com.zyj.mybatis.mapper.OrdersMapper">
<select id="findOrdersAndUserByRstType" resultType="com.zyj.mybatis.dto.OrdersExt">
SELECT orders.*, user.`username`, user.`sex` FROM orders, USER WHERE orders.`user_id` = user.`id`
</select>
</mapper>
// 测试代码
@Test
public void testFindOrdersAndUserByRstType() {
//......
List<OrdersExt> list = ordersMapper.findOrdersAndUserByRstType();
//......
}
小结:
1、一对一关联查询时,可以定义专门的扩展po类作为输出结果类型。
2、该扩展po类中定义了sql查询结果集所有的字段对应的属性。
3、此方法较为简单,企业中使用普遍。
方式二:resultMap
与方式一类似,扩展pojo类,与用户类User产生关联关系,并修改mapper映射文件
public class OrdersExt extends Orders {
private User user;
//省略getter和setter方法
}
// mapper接口
public interface OrdersMapper {
public List<OrdersExt> findOrdersAndUserByRstMap();
}
// mapper映射文件
<resultMap type="com.zyj.mybatis.dto.OrdersExt" id="OrdersAndUserRstMap">
<!-- 订单信息 -->
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 用户信息(一对一) -->
<!-- association:一对一关联映射 -->
<!-- property:关联信息查询的结果将要映射的扩展类中的对象属性名称 -->
<!-- id标签:建议在关联查询时必须写上,不写不会报错,但是会影响性能 -->
<association property="user" javaType="com.zyj.mybatis.po.User">
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
</association>
</resultMap>
<select id="findOrdersAndUserByRstMap" resultMap="OrdersAndUserRstMap">
SELECT
orders.*,
user.`username`,
user.`sex`
FROM
orders,
USER
WHERE orders.`user_id` = user.`id`
</select>
// 测试代码
@Test
public void testFindOrdersAndUserByRstType() {
//......
List<OrdersExt> list = mapper.findOrdersAndUserByRstMap();
//......
}
小结:
使用resultMap进行结果映射时,具体是使用association完成关联查询的映射,将关联查询信息映射到pojo对象中。
一对多(订单为主)
需求:查询订单列表,关联查询用户信息,而且同时附带相应的订单明细
sql语句:
SELECT
orders.id,
orders.`number`,
orders.`createtime`,
user.`username`,
user.`sex`,
orderdetail.`id` detailId,
orderdetail.`items_num`
FROM
orders,
USER,
orderdetail
WHERE orders.`user_id` = user.`id`
AND orders.`id` = orderdetail.`orders_id`
resultMap
public class OrdersExt extends Orders {
private User user;
private List<Orderdetail> details;
//省略getter和setter方法
}
// mapper接口
public interface OrdersMapper {
public List<OrdersExt> findOrdersAndDetailByRstMap();
}
// mapper映射文件
<!-- 这里extends继承了上面一对一的resultMap,对OdersExt关联的用户类User进行结果映射 -->
<!-- extends:可以继承一个已有的resultMap,指定resultMap的唯一标示即可 -->
<!-- 注意:继承时,只能继承type类型是一样的resultMap -->
<resultMap type="com.zyj.mybatis.dto.OrdersExt" id="OrdersAndDetailRstMap" extends="OrdersAndUserRstMap">
<!-- 订单明细信息(一对多) -->
<!-- collection:映射一对多关系 -->
<collection property="details" ofType="com.zyj.mybatis.po.Orderdetail">
<id column="detailId" property="id"/>
<result column="items_num" property="itemsNum"/>
</collection>
</resultMap>
<select id="findOrdersAndDetailByRstMap" resultMap="OrdersAndDetailRstMap">
SELECT
orders.id,
orders.`number`,
orders.`createtime`,
user.`username`,
user.`sex`,
orderdetail.`id` detailId,
orderdetail.`items_num`
FROM
orders,
USER,
orderdetail
WHERE orders.`user_id` = user.`id`
AND orders.`id` = orderdetail.`orders_id`
</select>
// 测试代码
@Test
public void testFindOrdersAndUserByRstType() {
//......
List<OrdersExt> list = mapper.findOrdersAndDetailByRstMap();
//......
}
多对多(用户为主)
需求:查询用户信息,关联查询该用户购买的商品信息
关系:一个用户对多个订单,一个订单对多个明细,一个明细对一个商品信息
sql语句:
SELECT
orders.id orders_id,
orders.`number`,
orders.`createtime`,
user.`id` user_id,
user.`username`,
user.`sex`,
orderdetail.`id` detail_id,
orderdetail.`items_num`,
items.`id` items_id,
items.`name`,
items.`price`
FROM
orders,
USER,
orderdetail,
items
WHERE orders.`user_id` = user.`id`
AND orders.`id` = orderdetail.`orders_id`
AND orderdetail.`items_id` = items.`id`
修改pojo类
public class User {
//一个用户对多个订单
private List<Orders> orders;
//...
}
public class Orders {
// 一个订单对多个明细
private List<Orderdetail> detail;
//...
}
public class Orderdetail {
//一条明细对一条商品信息
private Items items;
}
mapper接口
public interface UserMapper {
public List<User> findUserAndDetailByRstMap();
}
mapper映射文件
<!-- 多对多 -->
<resultMap type="com.zyj.mybatis.po.User" id="UserAndDetailRstMap">
<!-- 用户信息 -->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<!-- 一个用户对多个订单 -->
<collection property="orders" ofType="com.zyj.mybatis.po.Orders">
<!-- 订单信息 -->
<id column="orders_id" property="id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<!-- 一个订单对多个明细 -->
<collection property="detail" ofType="com.zyj.mybatis.po.Orderdetail">
<!-- 明细信息 -->
<id column="detail_id" property="id"/>
<result column="items_num" property="itemsNum"/>
<!-- 一条明细对一条商品信息 -->
<association property="items" javaType="com.zyj.mybatis.po.Items">
<!-- 商品信息 -->
<id column="items_id" property="id"/>
<result column="name" property="name"/>
<result column="price" property="price"/>
</association>
</collection>
</collection>
</resultMap>
<select id="findUserAndDetailByRstMap" resultMap="UserAndDetailRstMap">
SELECT
orders.id orders_id,
orders.`number`,
orders.`createtime`,
user.`id` user_id,
user.`username`,
user.`sex`,
orderdetail.`id` detail_id,
orderdetail.`items_num`,
items.`id` items_id,
items.`name`,
items.`price`
FROM
orders,
USER,
orderdetail,
items
WHERE orders.`user_id` = user.`id`
AND orders.`id` = orderdetail.`orders_id`
AND orderdetail.`items_id` = items.`id`
</select>
测试代码
@Test
public void testFindUserAndDetailByRstMap() {
//......
List<User> list = mapper.findUserAndDetailByRstMap();
//......
}
小结:
虽然resultMap和resultType都可以进行结果映射,但是使用resultType更加便捷,企业中建议使用resultType完成结果映射。
resultMap只有特殊场景才会用,比如延迟加载。