mybatis笔记02
0. 文章目录
Mybatis映射文件
动态SQL
关联查询
1. Mybatis映射文件
映射文件中select的两个参数重要参数:parameter和resultType
parameter: 输入映射,定义输入到sql中的映射类型,${value}表示使用参数将${value}替换,做字符串拼接。如果是取简单数量类型的参数,括号中的值必须为value。
resultType: 输出映射,定义结果映射类型。
1.1 输入映射
输入映射支持的数据类型:
- 基本数据类型:基础类型以及包装类、String
- POJO
- Map
- 包装的POJO:一个pojo中有pojo属性
输入映射参数为map类型举例
/mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.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.itzhouq.mybatis.mapper.UserMapper">
<!-- statementId -->
<select id="findById" parameterType="int" resultType="com.itzhouq.mybatis.pojo.User" >
select * from user where id = #{id}
</select> <insert id="insertUser" parameterType="com.itzhouq.mybatis.pojo.User">
<selectKey resultType="int" keyProperty="id" order="AFTER">
<!-- 返回当前事务最后产生的id值 -->
SELECT LAST_INSERT_ID();
</selectKey>
insert into user(username, birthday, sex, address) values(#{username}, #{birthday}, #{sex}, #{address});
</insert>
<select id="findUserByMap" parameterType="map" resultType="com.itzhouq.mybatis.pojo.User">
select * from user where username like '%${username}%' and sex = #{sex} and address=#{address}
</select> </mapper>
/mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.java
package com.itzhouq.mybatis.mapper; import java.util.List;
import java.util.Map; import com.itzhouq.mybatis.pojo.User; public interface UserMapper {
public User findById(int id); public void insertUser(User user);
//映射参数为map类型
public List<User> findUserByMap(Map<String, Object> map);
}
/mybatis-day02/src/com/itzhouq/mybatis/test/UserMapperTest.java
package com.itzhouq.mybatis.test; import java.io.IOException;
import java.util.HashMap;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test; import com.itzhouq.mybatis.mapper.UserMapper;
import com.itzhouq.mybatis.pojo.User; public class UserMapperTest {
SqlSessionFactory sqlSessionFactory = null;
@Before
public void init() throws IOException {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
sqlSessionFactory = builder.build(Resources.getResourceAsStream("sqlMapConfig.xml"));
} @Test
public void testFindById() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findById(28);
System.out.println(user);
sqlSession.close();
} @Test
public void testFindByMap() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Object> map = new HashMap<String, Object>();
// select * from user where username like '%张%' and sex = '1' and address='河南郑州'
// select * from user where username like '%${username}%' and sex = #{sex} and address=#{address}
map.put("username", "张");
map.put("sex", "1");
map.put("address", "河南郑州"); List<User> users= mapper.findUserByMap(map);
System.out.println(users);
sqlSession.close();
} }- 测试testFindByMap得到两个user对象
- 输入映射参数为包装的POJO类型举例
在pojo中新建一个类QueryVo
/mybatis-day02/src/com/itzhouq/mybatis/pojo/QueryVo.java
package com.itzhouq.mybatis.pojo; public class QueryVo {
private User user; public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
接口中/mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.java
package com.itzhouq.mybatis.mapper; import java.util.List;
import java.util.Map; import com.itzhouq.mybatis.pojo.QueryVo;
import com.itzhouq.mybatis.pojo.User; public interface UserMapper {
public User findById(int id); public void insertUser(User user);
//映射参数为map类型
public List<User> findUserByMap(Map<String, Object> map);
//映射参数为包装的POJO类型
public List<User> findUserByQueryVo(QueryVo queryVo); }
测试文件中/mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.xml添加
<select id="findUserByQueryVo" parameterType="queryVo" resultType="user">
<!-- queryVo
user
username -->
select * from user where username like '%${user.username}%'
</select>
测试类/mybatis-day02/src/com/itzhouq/mybatis/test/UserMapperTest.java
@Test
public void testFindByQueryVo() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
QueryVo queryVo = new QueryVo();
User user = new User();
user.setUsername("张");
queryVo.setUser(user);
List<User> users= mapper.findUserByQueryVo(queryVo);
System.out.println(users);
sqlSession.close();
}
1.2 输出映射
输出映射支持的数据类型:
- 基本数据类型:基础类型以及包装类、String
- POJO
- Map
- List
输出映射参数为map类型举例
接口com.itzhouq.mybatis.mapper.UserMapper
package com.itzhouq.mybatis.mapper; import java.util.List;
import java.util.Map; import com.itzhouq.mybatis.pojo.QueryVo;
import com.itzhouq.mybatis.pojo.User; public interface UserMapper {
public User findById(int id);
public void insertUser(User user);
//映射参数为map类型
public List<User> findUserByMap(Map<String, Object> map);
//映射参数为包装的POJO类型
public List<User> findUserByQueryVo(QueryVo queryVo);
//输出映射类型为int型
public int findUserCount();
//输出映射参数为map类型
public Map findById2(int id); }
映射配置文件/mybatis-day02/src/com/itzhouq/mybatis/mapper/UserMapper.xml中添加
<select id="findUserCount" resultType="int">
select count(*) from user;
</select>
测试类
@Test
public void testFindById2() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map map = mapper.findById2(28);
System.out.println(map);
//{birthday=2019-04-09, address=芭蕉洞, sex=0, id=28, username=玉面狐狸}
sqlSession.close();
}
1.3 resultMap
resultMap作用:当实体类的属性名和表的字段名不一致时,需要手动映射。
复制数据库中的user表为user_copy1,更改其中的username和sex字段,这时候这两个字段和实体类User中的属性名就不一致了。
更改后的表和类需要正常映射的话,需要手动配置resultMap
<resultMap id="findById3ResultMap" type="user">
<id column="id" property="id"/>
<result column="user_name" property="username"/>
<result column="gender" property="sex"/>
<!-- <result column="birthday" property="birthday"/>
<result column="address" property="address"/> -->
</resultMap>
<select id="findById3" parameterType="int" resultMap="findById3ResultMap" >
select * from user_copy1 where id = #{id}
</select>
- 字段相同的列可以省略不用手动配置
2. 动态SQL
2.1 if和where
需求分析:实际开发过程中,会用到组合条件查询,条件的个数是不固定的,这就要求sql语句中的条件根据传入的参数动态改变。为此,mybatis引入了where和if标签产生动态sql。
示例:
UserMapper.java文件中添加一个方法
//动态Sql
public List<User> findListByUser(User user);
xml配置文件
<select id="findListByUser" parameterType="user" resultType="user">
select * from user
<where>
<if test="username!=null and username!=''">
username like '%${username}%'
</if>
<if test="sex!=null and sex!=''">
and sex = #{sex}
</if>
<if test="address!=null and address!=''">
and address=#{address}
</if>
</where>
</select>- if作用:判断
- where作用:取出第一个and或者or
测试
@Test
public void testFindListByUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
// user.setUsername("张");
user.setSex("1");
user.setAddress("河南郑州");
List<User> list= mapper.findListByUser(user);
System.out.println(list);
sqlSession.close();
}
mybatis可以根据user中条件个数动态生成sql语句
比如上面代码中两个条件下,生成的sql语句为:
DEBUG [main] - ==> Preparing: select * from user WHERE sex = ? and address=?
2.2 foreach循环
需求分析:要查询用户id为1 16 22 的用户信息,相对应的sql语句为 SELECT * FROM
user
where id in (1, 16, 22)。查询的参数是数组,把这个数组放在包装类中传递。接口文件中添加
//动态sql,foreach循环
public List<User> findListByArray(QueryVo queryVo);
包装类中添加数组ids
package com.itzhouq.mybatis.pojo; public class QueryVo {
private User user; int[] ids; public int[] getIds() {
return ids;
}
public void setIds(int[] ids) {
this.ids = ids;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
映射配置文件
<select id="findListByArray" parameterType="queryVo" resultType="user">
<!-- queryVo -->
<!-- ids = [ 1, 16, 22] -->
<!-- SELECT * FROM `user` where id in (1, 16, 22) -->
<!-- select * from user where id in -->
SELECT * FROM `user` where id in
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</select>
测试类
@Test
public void testFindListByArray() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
QueryVo queryVo = new QueryVo();
int[] ids = {1, 16, 22};
queryVo.setIds(ids);
List<User> list= mapper.findListByArray(queryVo);
System.out.println(list);
sqlSession.close();
}
生成的sql语句
DEBUG [main] - ==> Preparing: SELECT * FROM user where id in ( ? , ? , ? )
2.3 sql片段 sql+include
sql片段主要是用于xml文件中的代码复用
<select id="findListByUser" parameterType="user" resultType="user">
select * from user
<include refid="findUserWhere"></include>
</select>
<sql id="findUserWhere">
<where>
<if test="username!=null and username!=''">
username like '%${username}%'
</if>
<if test="sex!=null and sex!=''">
and sex = #{sex}
</if>
<if test="address!=null and address!=''">
and address=#{address}
</if>
</where>
</sql>
2.4 set
需求分析:在更新数据库操作时,有可能只是更改某几个字段,传递的数据类型为user时,如果user的某些属性没有赋值,相当于把这些数据库中的这些字段设为null或者默认值,这样不符合我们的需求。这就需要判断user中的属性是否为空了。但是结合sql语句,修改操作时,每个字段后面又一个逗号。这里需要需要使用set去掉逗号,保证生成sql语句的正确性。
接口代码
//动态sql,set
public void updateUser(User user);
映射文件中添加
<update id="updateUser" parameterType="user">
<!-- update user set username=#{username},sex=#{sex},
birthday=#{birthday},address=#{address} where id=#{id} -->
update user
<set>
<if test="username != null and username != ''">
username=#{username},
</if>
<if test="sex != null and sex != ''">
sex=#{sex},
</if>
<if test="birthday != null">
birthday=#{birthday},
</if>
<if test="address != null and address != ''">
address=#{address},
</if>
</set>
where id=#{id}
</update>
测试类
@Test
public void testUpdateUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(28);
user.setUsername("铁扇公主");
mapper.updateUser(user);
sqlSession.commit();
sqlSession.close();
}
生成的sql语句
DEBUG [main] - ==> Preparing: update user SET username=? where id=?
4. 关联查询
4.1 商品订单数据模型
4.2 一对一查询
- 案例:查询所有订单信息,关联查询下单用户信息
- 因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联用户信息为一对一查询。如果从用户信息出发下的订单则会为一对多查询,因为一个用户可以下多个订单。
4.2.1 方法一:
使用resultType,定义订单信息pojo类,此pojo类中包括了订单信息和用户信息。
sql语句
select o.*,u.username,u.address,u.birthday,u.sex from orders o left join user u on o.user_id = u.id
新建pojo类,OrdersUser,这个类中应该包括sql查询出来的所有字段
public class OrdersUser {
private int id;
private int user_id;
private String number;
private Date createtime;
private String note;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
- OrdersMapper.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.itzhouq.mybatis.mapper.OrdersMapper">
<!-- statementId -->
<select id="findOrdersUserList" resultType="ordersUser" >
select o.*,u.username,u.address,u.birthday,u.sex from
orders o left join user u on o.user_id = u.id
</select>
</mapper>
- 测试类OrdersMapperTest.java
package com.itzhouq.mybatis.test; import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test; import com.itzhouq.mybatis.mapper.OrdersMapper;
import com.itzhouq.mybatis.mapper.UserMapper;
import com.itzhouq.mybatis.pojo.OrdersUser;
import com.itzhouq.mybatis.pojo.QueryVo;
import com.itzhouq.mybatis.pojo.User; public class OrdersMapperTest {
SqlSessionFactory sqlSessionFactory = null;
@Before
public void init() throws IOException {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
sqlSessionFactory = builder.build(Resources.getResourceAsStream("sqlMapConfig.xml"));
} @Test
public void testFindOrdersUserList() {
SqlSession sqlSession = sqlSessionFactory.openSession();
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
List<OrdersUser> ordersUserList = mapper.findOrdersUserList();
System.out.println(ordersUserList);
sqlSession.close(); }
}查询结果与数据库中相同
- 定义专门的pojo类作为输出类型,其中定了sql查询结果集所有的字段,此方法较为简单。
4.2.2 方法2:
使用resultMap,定义resultMap用于映射一对一的查询结果。
select o.*,u.username,u.address,u.birthday,u.sex from orders o left join user u on o.user_id = u.id
定义pojo类:早Orders类中加入Users属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一的关系,所以这使用单个User对象存储关联查询的用户信息。
public class Orders {
private int id;
private int user_id;
private String number;
private Date createtime;
private String note; private User user; public int getId() {
return id;
}
映射文件OrdersMapper.xml
<resultMap id="ordersResultMap" type="orders" >
<id column="id" property="id"/>
<result column="user_id" property="user_id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 构建一对一级联关系 -->
<association property="user" javaType="com.itzhouq.mybatis.pojo.User">
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="address" property="address"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
</association>
</resultMap> <select id="findOrdersList" resultMap="ordersResultMap" >
select o.*,u.username,u.address,u.birthday,u.sex from
orders o left join user u on o.user_id = u.id
</select>
这里resultMap指定ordersResultMap。
:表示进行关联查询的单条记录
property:表示关联查询到结果存储在com.itzhouq.mybatis.pojo.User中
javaType:表示关联查询的结果类型
:查询结果的user_id列对象关联对象的id属性,这里是表示user_id是关联对象的唯一标识。
- OrdersMapper接口
public interface OrdersMapper {
public List<OrdersUser> findOrdersUserList(); public List<Orders> findOrdersList();
}
测试
@Test
public void testFindOrdersList() {
SqlSession sqlSession = sqlSessionFactory.openSession();
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
List<Orders> ordersList = mapper.findOrdersList();
System.out.println(ordersList);
sqlSession.close();
}
总结:使用association完成关联查询,将关联查询信息映射到pojo对象中。
4.3 一对多查询
案例:查询所有用户信息及用户相关联的订单信息
用户信息和订单信息为一对多的关系
sql语句
定义pojo类:在User中添加
public class User implements Serializable {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址 private List<Orders> ordersList;
映射文件OrdersMapper.xml
<resultMap type="user" id="UserResultMap">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="address" property="address"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<!-- public List<User> findUserList(); -->
<!-- collection:一对多关联,ofType集合中包含的属性 -->
<collection property="ordersList" ofType="com.itzhouq.mybatis.pojo.Orders">
<id column="oid" property="id"/>
<result column="id" property="user_id"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
</collection>
</resultMap>
<select id="findUserList" resultMap="UserResultMap">
select u.*,o.id oid,o.number,o.createtime,o.note from user u
inner join orders o on o.user_id = u.id
</select>
collection部分定义了用户关联的订单信息。表示关联查询结果集
property="orders":关联查询的结果集存储在User对象的上哪个属性。
ofType="orders":指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
<id />及<result/>的意义同一对一查询。
接口
public interface OrdersMapper {
public List<OrdersUser> findOrdersUserList(); public List<Orders> findOrdersList();
//查询User,User中关联多个订单
public List<User> findUserList();
}
测试
@Test
public void testFindUserList() {
SqlSession sqlSession = sqlSessionFactory.openSession();
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
List<User> userList = mapper.findUserList();
System.out.println(userList);
sqlSession.close();
}
- 结果与数据库中查询的结果一致。
mybatis笔记02的更多相关文章
- 软件测试之loadrunner学习笔记-02集合点
loadrunner学习笔记-02集合点 集合点函数可以帮助我们生成有效可控的并发操作.虽然在Controller中多用户负载的Vuser是一起开始运行脚本的,但是由于计算机的串行处理机制,脚本的运行 ...
- 《30天自制操作系统》笔记(02)——导入C语言
<30天自制操作系统>笔记(02)——导入C语言 进度回顾 在上一篇,记录了计算机开机时加载IPL程序(initial program loader,一个nas汇编程序)的情况,包括IPL ...
- 《The Linux Command Line》 读书笔记02 关于命令的命令
<The Linux Command Line> 读书笔记02 关于命令的命令 命令的四种类型 type type—Indicate how a command name is inter ...
- 强化学习读书笔记 - 02 - 多臂老O虎O机问题
# 强化学习读书笔记 - 02 - 多臂老O虎O机问题 学习笔记: [Reinforcement Learning: An Introduction, Richard S. Sutton and An ...
- Mybatis笔记二:接口式编程
目录 旧方法的弊端 接口式编程 接口式编程的好处 接口式编程的增删改查 旧方法的弊端 在Mybatis笔记一中,我们使用命名空间+id的方式实现了Mybatis的执行,不过这里的命名空间是我们随便写的 ...
- JS自学笔记02
JS自学笔记02 1.复习 js是一门解释性语言,遇到一行代码就执行一行代码 2.查阅mdn web文档 3.提示用户输入并接收,相比之下,alert只有提示的作用: prompt(字符串) 接收: ...
- 机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN)
机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN) 关键字:邻近算法(kNN: k Nearest Neighbors).python.源 ...
- CS229 笔记02
CS229 笔记02 公式推导 $ {\text {For simplicity, Let }} A, B, C \in {\Bbb {R}}^{n \times n}. $ $ {\bf {\t ...
- OpenCV 学习笔记 02 使用opencv处理图像
1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...
随机推荐
- 关于浏览器跨域的一种实现--jsonp
最近一直在搞python,前端技术荒废很久了,今天跟前端联调,设计到一个前端跨域的问题:前端人员告诉我可以用jsonp的方式实现,经他这么一提醒,也是豁然开朗. jsonp的实现方式我按照我的理解说一 ...
- 背水一战 Windows 10 (96) - 选取器: ContactPicker
[源码下载] 背水一战 Windows 10 (96) - 选取器: ContactPicker 作者:webabcd 介绍背水一战 Windows 10 之 选取器 ContactPicker(联系 ...
- css3动画:transition和animation
概述 之前写过css3 动画与display:none冲突的解决方案,但是最近却发现,使用animation效果比transition好得多,而且不和display:none冲突.下面我把相关新的记录 ...
- SpringBoot集成Thymeleaf模板引擎
简单介绍 目前在JavaEE领域有几中比较常用的模板引擎,分别是Jsp.Velocity.Freemarker.Thymeleaf,对Freemark语法不是特别熟悉,不过对于前端页面渲染效率来说,j ...
- SpringMvc参数传递中乱码问题
问题描述: 当传递中文参数到controller类时,无乱是get方式还是post方式都出现乱码 解决: 1.保证所有的页面编码都是utf-8,包括jsp页面,浏览器编码设置和eclipse的编码设置 ...
- .Net 环境下比较各种数据库插入操作的性能
1.简介 再说Windows的异步I/O操作前,先聊聊一些题外话,能帮助我们更好的理解异步I/O操作,常规的Web程序,当用户发起一次请求,当请求通过管道到达客户端的这个过程,会唤起一个线程池线程(后 ...
- IdentityServer4(8)- 使用密码认证方式控制API访问(资源所有者密码授权模式)
一.前言 本文已经更新到 .NET Core 2.2 OAuth 2.0 资源所有者密码模式允许客户端向令牌服务发送用户名和密码,并获取代表该用户的访问令牌. 除了通过无法浏览器进行交互的应用程序之外 ...
- ES搜索结果调优
访问我的博客 自从使用 ElasticSearch 重构了主站的搜索项目之后,之后又陆续接入了其他两个项目,目前使用 SpringBoot 方式跑了一个伪集群,主站使用的时候,比较稳定,没有人反馈说有 ...
- Kubernetes理论基础
Kubernetes理论基础 Kubernetes定义 kubernetes是Google开源的容器集群管理系统,2014年6月开源.在Docker技术之上,为容器应用提供资源调度.部署运行.服务 ...
- Map<String, Object>转Object,Object转 Map<String, Object>
Map转Object import com.alibaba.fastjson.JSON; Map<String, Object> boneAgeOrderMap=boneAgeOrderS ...