mybatis02
多表操作
一对一(多对一)
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 {}
完