多表操作
一对一(多对一)
User , Account
实现查询账户信息时,也要查询账户所对应的用户信息。
SELECT account.*, user.username, user.address FROM account, user WHERE account.uid = user.id
方式一
定义 AccountCustomer 类中要包含账户信息同时还要包含用户信息,所以要在定义 AccountUser 类时可以继承 User 类
1 public class AccountUser extends Account implements Serializable {
2 private String username;
3 private String address;
4 //getter setter
5
6 }
IAccountDao
List<AccountUser> findAll();
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.qyy.dao.IAccountDao"> 6 <!-- 配置查询所有操作--> 7 <select id="findAll" resultType="accountuser"> 8 select a.*,u.username,u.address from account a,user u where a.uid =u.id; 9 </select> 10 </mapper>
方式二
使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果
在 Account 类中加入一个 User 类的对象 ,它可以封装账户所对应的用户信息
Account
1 public class Account implements Serializable {
2
3 //
4
5 private User user;
6
7 //getter setter
8
9
10
11 }
IAccountDao
List<Account> findAll();
AccountDao.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.qyy.dao.IAccountDao"> 6 <!-- 建立对应关系 --> 7 <resultMap type="account" id="accountMap"> 8 <id column="aid" property="id"/> 9 <result column="uid" property="uid"/> 10 <result column="money" property="money"/> 11 <!-- 它是用于指定从表方的引用实体属性的 --> 12 <association property="user" javaType="user"> 13 <id column="id" property="id"/> 14 <result column="username" property="username"/> 15 <result column="sex" property="sex"/> 16 <result column="birthday" property="birthday"/> 17 <result column="address" property="address"/> 18 </association> 19 </resultMap> 20 <select id="findAll" resultMap="accountMap"> 21 select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id; 22 </select> 23 </mapper>
一对多
查询所有用户信息及用户关联的账户信息,查询过程中如果用户没有账户信息,此时也要将用户信息查询出来
SELECT u.*, acc.id id, acc.uid, acc.money FROM user u LEFT JOIN account acc ON u.id = acc.uid
User类加入Account
1 public class User implements Serializable {
2
3 ...
4
5
6 private List<Account> accounts;
7 //setter getter
8
9 }
List<User> findAll();
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.qyy.dao.IUserDao"> 6 <resultMap type="user" id="userMap"> 7 <id column="id" property="id"></id> 8 <result column="username" property="username"/> 9 <result column="address" property="address"/> 10 <result column="sex" property="sex"/> 11 <result column="birthday" property="birthday"/> 12 <!-- collection 是用于建立一对多中集合属性的对应关系 13 ofType 用于指定集合元素的数据类型 14 --> 15 <collection property="accounts" ofType="account"> 16 <id column="aid" property="id"/> 17 <result column="uid" property="uid"/> 18 <result column="money" property="money"/> 19 </collection> 20 </resultMap> 21 <!-- 配置查询所有操作 --> 22 <select id="findAll" resultMap="userMap"> 23 select u.*,a.id as aid ,a.uid,a.money from user u left outer join account 24 a on u.id =a.uid 25 </select> 26 </mapper>
collection
部分定义了用户关联的账户信息。表示关联查询结果集
property=""
关联查询的结果集存储在 User 对象的上哪个属性。
ofType=""
指定关联查询的结果集中的对象类型即 List中的对象类型。此处可以使用别名,也可以使用全限定名
association:将关联查询信息映射到一个pojo对象中。
collection:将关联查询信息映射到一个list集合中。
多对多

实现查询所有对象,并且加载它所分配的用户信息 (Role 到 User)
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
Role
1 public class Role implements Serializable {
2
3 ...
4
5 //多对多的关系映射:一个角色可以赋予多个用户
6 private List<User> users;
10 //setter getter
11
12 }
List<Role> findAll();
<?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.qyy.dao.IRoleDao"> <!--定义 role 表的 ResultMap--> <resultMap id="roleMap" type="role"> <id property="roleId" column="rid"></id> <result property="roleName" column="role_name"></result> <result property="roleDesc" column="role_desc"></result> <collection property="users" ofType="user"> <id column="id" property="id"></id> <result column="username" property="username"></result> <result column="address" property="address"></result> <result column="sex" property="sex"></result> <result column="birthday" property="birthday"></result> </collection> </resultMap> <!--查询所有--> <select id="findAll" 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> </mapper>
实现查询所有用户信息并关联查询出每个用户的角色列表 (User 到 Role)
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
延迟加载
就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载
1 <settings> 2 <setting name="lazyLoadingEnabled" value="true"/> 3 <setting name="aggressiveLazyLoading" value="false"/> 4 </settings>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <mapper namespace="com.itheima.dao.IAccountDao"> 7 <resultMap id="accountUserMap" type="Account"> 8 <id property="id" column="id"></id> 9 <result property="uid" column="uid"></result> 10 <result property="money" column="money"></result> 11 <association property="user" column="uid" javaType="User" 12 select="com.qyy.dao.IUserDao.findById"> 13 </association> 14 </resultMap> 15 16 17 <select id="findAll" resultMap="accountUserMap"> 18 SELECT * FROM account 19 </select> 20 21 22 </mapper>
select: 是用于指定查询账户的唯一标识
column : 填写我们要传递给 select 映射的参数
mybatis缓存
一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在 ,当调用 SqlSession 的修改,添加,删除, commit(), close()等
方法时,就会清空一级缓存。
二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个
SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的
配置
SqlMapConfig.xml
<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>
mapper映射文件
<!-- 开启二级缓存的支持 -->
<cache></cache>
配置 statement 上面的 useCache 属性
useCache="true"
mybatis常用注解,
不需要再去编写 xml 映射文件
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@ResultMap:实现引用@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用
举例:
对象名与列名不一致
1 @Select("select * from user")
2 @Results(id="userMap",
3 value= {
4 @Result(id=true,column="id",property="userId"),
5 @Result(column="username",property="userName"),
6 @Result(column="sex",property="userSex"),
7 @Result(column="address",property="userAddress"),
8 @Result(column="birthday",property="userBirthday")
9 })
10 List<User> findAll();
多表关系注解
@Results 注解
代替的是标签<resultMap>
该注解中可以使用单个@Result 注解,也可以使用@Result 集合
@Results({@Result(), @Result() })或@Results(@Result())
@Result代替了 <id>标签和<result>标签
@Result 中 属性介绍:
id 是否是主键字段
column 数据库的列名
property 需要装配的属性名
one 需要使用的@One 注解(@Result(one=@One)()))
many 需要使用的@Many 注解(@Result(many=@many)()))
@One 注解(一对一)
代替了<assocation>标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
@One 注解属性介绍:
select 指定用来多表查询的 sqlmapper
fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。。
使用格式:
@Result(column=" ",property="",one=@One(select=""))
@Many 注解(多对一)
代替了<Collection>标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。
注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType
(一般为 ArrayList)但是注解中可以不定义;
使用格式:
@Result(property="",column="",many=@Many(select=""))
举例:一对一实现复杂关系映射
加载账户信息时并且加载该账户的用户信息,根据情况可实现延迟加载
IAccountDao
1 @Select("select * from account")
2 @Results(id="accountMap",
3 value= {
4 @Result(id=true,column="id",property="id"),
5 @Result(column="uid",property="uid"),
6 @Result(column="money",property="money"),
7 @Result(column="uid",
8 property="user",
9 one=@One(select="com.qyy.dao.IUserDao.findById",
10 fetchType=FetchType.LAZY)
11 )
12 })
13 List<Account> findAll();
IUserDao
1 /**
2 * 查询所有用户
3 * @return
4 */
5 @Select("select * from user")
6 @Results(id="userMap",
7 value= {
8 @Result(id=true,column="id",property="userId"),
9 @Result(column="username",property="userName"),
10 @Result(column="sex",property="userSex"),
11 @Result(column="address",property="userAddress"),
12 @Result(column="birthday",property="userBirthday")
13 })
14 List<User> findAll();
15 /**
16 * 根据 id 查询一个用户
17 * @param userId
18 * @return
19 */
20 @Select("select * from user where id = #{uid} ")
21 @ResultMap("userMap")
22 User findById(Integer userId);
23 }
注解实现一对多
查询用户信息时,也要查询他的(多个)账户列表
IUserDao
1 @Select("select * from user")
2 @Results(id="userMap",
3 value= {
4 @Result(id=true,column="id",property="userId"),
5 @Result(column="username",property="userName"),
6 @Result(column="sex",property="userSex"),
7 @Result(column="address",property="userAddress"),
8 @Result(column="birthday",property="userBirthday"),
9 @Result(column="id",property="accounts",
10 many=@Many(
11 select="com.qyy.dao.IAccountDao.findByUid",
12 fetchType=FetchType.LAZY
13 )
14 )
15 })
16 List<User> findAll();
17 }
18 @Many:
19 相当于<collection>的配置
20 select 属性:代表将要执行的 sql 语句
21 fetchType 属性:代表加载方式,一般如果要延迟加载都设置为 LAZY 的值
IAccountDao
1 //根据用户 id 查询用户下的所有账户
2 @Select("select * from account where uid = #{uid} ")
3 List<Account> findByUid(Integer userId);
持久层接口配置二级缓存
1 @CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存
2 public interface IUserDao {}
完