1.if标签:
条件查询:当不清楚用户输入的查询条件具体为什么时,使用if标签来包裹该部分条件
例如:
通过传入User对象来返回模糊查询的List<User>,该User对象中可能有username,sex等某一些信息,或者都有
此时,不能确定最终的查询语句,使用if标签来动态生成sql语句
<select id="findUserByCondition" resultType="cn.mysilent.domian.User" parameterType="user">
select * from user where 1=1<if test="username != null">
and username=#{username}</if><if test="sex != null">
and sex=#{sex}</if>....</select>2. where标签:
在动态生成sql语句时,避免出现类似1=1的条件,直接将if标签嵌套进where标签中
例如:
<select id="findUserByCondition" resultType="cn.mysilent.domian.User" parameterType="user">
select * from user
<where><if test="username != null">
and username=#{username}</if><if test="sex != null">
and sex=#{sex}</if>....</where></select>3. foreach标签:
在原始sql语句中,可以正常书写查询id在某个集合中的数据项:
select * from user where id in (1,2,3,4);
于是在mybatis中动态生成sql语句需要使用foreach标签
例如:
<!--在QueryVo对象中创建一个ArrayList存储查询的id集合成员变量属性名为ids--><select id="findUserByIds" resultType="cn.mysilent.domian.User" parameterType="QueryVo">
select * from user
<where><if test="ids != null and ids.size()>0"><!--仅ids中有值存在时添加该条件--><foreach collection="ids" open=" and id in (" close=")" item="uid" separator=","><!--取出遍历的临时变量中的值-->
#{uid}</foreach></if></where></select>
foreach标签的各属性含义
collection:要遍历的集合对象,不需要#{}
open:代表语句的开始部分
close:代表语句的结束
item:代表遍历时的临时变量
separator:表示遍历后元素间的分隔符
mybatis中的多表查询
1. 表与表之间关系
a. 一对一
b. 一对多
c. 多对多
d. 多对一(mybatis中将多对一看作多个一对一)2. mybatis中实现多表查询:
示例:用户和账户
一个用户可以有多个账户
一个账户只能属于一个用户(多个账户可以属于同一个用户)
步骤:
1. 建立两张表:用户表,账户表
用户(1): 账户(n)
需要在n的一方(账户)添加外键列,关联用户表的主键
2. 建立两个实体类:用户实体类和账户实体类
需要让两个实体类体现出表之间的关系
在用户实体类中定义List成员变量存放账户实体类的引用
在账户实体类中定义用户实体类的引用
3. 建立两个配置文件:
用户表操作的配置文件 -- 创建IUserDao接口
账户表操作的配置文件 -- 创建IAccountDao接口
4. 实现配置:
* 当查询用户时,可以同时得到用户下所包含的所有账户信息
* 当查询账户时,可以同时得到账户所属的用户信息
配置文件要点:
1. 一对一:在账户实体类中包含了用户实体类的引用
原始sql语句:
select u.*, a.id as aid, a.uid, a.money from account a, user u where u.id=a.uid
如此可以查询出每一账户关联的用户信息
IAccountDao配置文件:
需要将查询出来的结果封装到account类对应的成员变量中和user类引用的对象的成员变量中
此时需要使用resultMap标签来定制自定义的结果集:
结果集配置:
<!--最外层的type依旧为账户类的类型(用户类引用封装在该类中),此处使用了别名--><resultMap id="accountUserMap" type="accout"><!--账户表主键--><id property="id" column="aid"></id><!--账户表非主键--><result property="uid" column="uid"></result><result property="money" column="money"></result><!--配置账户表中一对一映射关系,使用association标签,封装user的内容--><!--其中property为账户类中用户类成员变量的属性名,column属性为关联的对对应的外键列--><!--javaType表示association标签内的数据封装为的实体类全限定类名(可以使用别名)--><association property="user" column="uid" javaType="cn.mysilent.domain.User"><!--用户表主键--><id property="id" column="id"></id><!--用户表非主键--><result property="username" column="username"></result><result property="address" column="address"></result><result property="sex" column="sex"></result><result property="birthday" column="birthday"></result></association></resultMap>
sql语句配置:
<select id="findAllAccount" resultMap="accountUserMap">
select u.*, a.id as aid, a.uid, a.money from account a, user u where u.id=a.uid
</select>
输出结果:
sout(account);sout(assount.getUser());2. 一对多:在用户实体类中包含账户对象引用列表
原始sql语句:查询出用户所有信息并且该用户下所包含的所有账号信息,没有账户的用户账户列为null值
使用左外连接保证user表中的信息完整
select
u.*, a.id as aid, a.uid, a.money
from
user u
left outer join
account a
on
u.id = a.uid
由此,可以产生结果集:
如果用户没有账户,则该用户数据行账户信息为null
如果该用户有账户,则每个账户与用户信息组合为一条数据
IUserDao配置文件:
需要将查询出来的结果封装到user类对应的成员变量中和account类引用列表中对象的成员变量中
此时需要使用resultMap标签来定制自定义的结果集:
结果集配置:
<!--最外层的type为用户类的类型(账户类引用列表封装在该类中),此处使用了别名--><resultMap id="userAccountMap" type="user"><!--用户表主键--><id property="id" column="id"></id><!--用户表非主键--><result property="username" column="username"></result><result property="address" column="address"></result><result property="sex" column="sex"></result><result property="birthday" column="birthday"></result><!--配置用户表中一对多映射关系,使用collection标签,表示封装的是一个集合--><!--其中property为用户类中账户类列表成员变量的属性名--><!--ofType表示集合内的数据封装为的实体类全限定类名(可以使用别名)--><collection property="accounts" ofType="cn.mysilent.domain.Account"><!--账户表主键--><id property="id" column="aid"></id><!--账户表非主键--><result property="uid" column="uid"></result><result property="money" column="money"></result></collection></resultMap>
sql语句配置:
<select id="findAllUser" resultMap="userAccountMap">
select u.*, a.id as aid, a.uid, a.money from user u
left outer join account a on u.id = a.uid
</select>
输出结果:
sout(user);sout(user.getAccounts());3. mybatis中多对多查询:
示例:用户和角色
一个用户可以有多个角色
一个角色可以属于多个用户
步骤:
1. 建立两张表:用户表,角色表
用户(n): 角色(m)
需要使用一张中间表,包含各自的主键,在中间表中作为外键
2. 建立两个实体类:用户实体类和账户实体类
需要让两个实体类体现出表之间的关系
在用户实体类中定义List成员变量存放角色实体类的引用
在角色实体类中定义List成员变量存放用户实体类的引用
3. 建立两个配置文件:
用户表操作的配置文件 -- 创建IUserDao接口
角色表操作的配置文件 -- 创建IRoleDao接口
4. 实现配置:
* 当查询用户时,可以同时得到用户下所包含的所有角色信息
* 当查询角色时,可以同时得到角色所属的所有用户信息
配置文件要点:
1. 多对多:在角色实体类中包含用户实体类引用集合
原始sql语句:查询角色表时,如果该角色有所属用户,则列举所有用户,没有所属则用户信息为null
select u.*, r.id as rid, r.role_name, r.role_desc from role r
left outer join user_role ur on r.id=ur.rid
left outer join user u on u.id=ur.uid
使用两次左外连接实现效果
IRoleDao配置文件:
自定义查询的结果集:
<!--最外层的type为角色类的类型(用户类引用列表封装在该类中),此处使用了别名--><resultMap id="roleMap" type="role"><!--角色表主键,cloumn在sql语句中起了别名,则此处用别名--><id property="roleId" column="rid"></id><!--角色表非主键--><result property="roleName" column="role_name"></result><result property="roleDesc" column="role_desc"></result><!--配置角色表中多对多映射关系,使用collection标签,表示封装的是一个集合--><!--其中property为用户类中角色类列表成员变量的属性名--><!--ofType表示集合内的数据封装为的实体类全限定类名(可以使用别名)--><collection property="users" ofType="cn.mysilent.domain.User"><!--用户表主键--><id property="id" column="id"></id><!--用户表非主键--><result property="username" column="username"></result><result property="address" column="address"></result><result property="sex" column="sex"></result><result property="birthday" column="birthday"></result></collection></resultMap>
sql语句配置:
<select id="findAllRole" resultMap="roleMap">
select u.*, r.id as rid, r.role_name, r.role_desc from role r
left outer join user_role ur on r.id=ur.rid
left outer join user u on u.id=ur.uid
</select>
输出结果:
sout(role);sout(role.getUsers());2. 多对多:在用户实体类中包含角色实体类引用集合
原始sql语句:查询用户表时,如果该用户具有角色,列举所包含的角色信息,没有角色则角色信息为null
select u.*, r.id as rid, r.role_name, r.role_desc from user u
left outer join user_role ur on u.id=ur.uid
left outer join role r on r.id=ur.rid
使用两次左外连接实现效果
IUserDao配置文件:
自定义查询的结果集:
<!--最外层的type为用户类的类型(用户类引用列表封装在该类中),此处使用了别名--><resultMap id="userMap" type="user"><!--用户表主键--><id property="id" column="id"></id><!--用户表非主键--><result property="username" column="username"></result><result property="address" column="address"></result><result property="sex" column="sex"></result><result property="birthday" column="birthday"></result><!--配置用户表中多对多映射关系,使用collection标签,表示封装的是一个集合--><!--其中property为用户类中角色类列表成员变量的属性名--><!--ofType表示集合内的数据封装为的实体类全限定类名(可以使用别名)--><collection property="roles" ofType="cn.mysilent.domain.Role"><!--账户表主键,cloumn在sql语句中起了别名,则此处用别名--><id property="id" column="rid"></id><!--账户表非主键--><result property="roleName" column="role_name"></result><result property="roleDesc" column="role_desc"></result></collection></resultMap>
sql语句配置:
<select id="findAllRole" resultMap="roleMap">
select u.*, r.id as rid, r.role_name, r.role_desc from user u
left outer join user_role ur on u.id=ur.uid
left outer join role r on r.id=ur.rid
</select>
输出结果:
sout(user);sout(user.getRoles());