day04 mybatis
1.多对多查询
1.1 多对多查询的模型
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求:查询用户同时查询出该用户的所有角色
1.2 多对多查询的语句
SELECT * FROM USER u, sys_user_role ur, sys_role r WHERE u.id=ur.userId AND ur.roleId=r.id
查询结果如下:
1.3 创建Role实体,修改User实体
package com.atguigu.pojo;
public class Role {
private String id;
private String rolename;
private String roleDesc;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
}
@Override
public String toString() {
return "Role{" +
"id='" + id + '\'' +
", rolename='" + rolename + '\'' +
", roleDesc='" + roleDesc + '\'' +
'}';
}
}
package com.atguigu.pojo;
import java.util.Date;
import java.util.List;
public class User {
private Integer id;
private String username;
private String password;
private Date birthday;
// 代表当前用户具备哪些订单
private List<Orders> ordersList;
// 代表当前用户具备i那些角色
private List<Role> roleList;
public List<Role> getRoleList() {
return roleList;
}
public void setRoleList(List<Role> roleList) {
this.roleList = roleList;
}
public List<Orders> getOrdersList() {
return ordersList;
}
public void setOrdersList(List<Orders> ordersList) {
this.ordersList = ordersList;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", birthday=" + birthday +
", roleList=" + roleList +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
1.4 添加UserDao接口方法
List<User> findUserAndRoleAll();
1.5 配置UserDao.xml
<resultMap id="userRoleMap" type="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<!-- user内部的roleList信息-->
<collection property="roleList" ofType="Role">
<result column="id" property="id"></result>
<result column="rolename" property="rolename"></result>
<result column="roleDesc" property="roleDesc"></result>
</collection>
</resultMap>
<select id="findUserAndRoleAll" resultMap="userRoleMap">
select * from user u,sys_role r,sys_user_role ur where u.id = ur.roleid and r.id = ur.roleid;
</select>
1.6 测试结果
@Test
public void testFindUserAndRoleAll(){
List<User> userList = userDao.findUserAndRoleAll();
for (User user : userList) {
System.out.println(user);
}
}
2.Mybatis延迟加载策略
2.1 一对一延迟加载
通过前面的学习,我们已经掌握了 Mybatis 中一对一,一对多,多对多关系的配置及实现,可以实现对象的关联查询。实际开发过程中很多时候我们并不需要总是在加载用户信息时就一定要加载他的账户信息。此时就是我
们所说的延迟加载。
延迟加载:
就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
创建项目mybatis_lazy
需求:
查询账号信息同时查询用户信息
2.1.1 创建OrderDao.java
package com.atguigu.dao;
import com.atguigu.pojo.Orders;
import java.util.List;
public interface OrdersDao {
/**
* 查询所有订单 同时获取订单的所属用户名称以及它的信息
* @return
*/
List<Orders> findAll();
}
2.1.2 创建OrderDao.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.atguigu.dao.OrdersDao">
<!--查询所有
select: 填写我们要调用的 select 映射的 id
column : 填写我们要传递给 select 映射的参数
-->
<resultMap id="ordersMap" type="Orders">
<id column="id" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
<association property="user" javaType="User" column="uid" select="com.atguigu.dao.UserDao.findById">
</association>
</resultMap>
<select id="findAll" resultMap="ordersMap">
select * from orders
</select>
</mapper>
2.1.3 创建UserDao.java
package com.atguigu.dao;
import com.atguigu.pojo.User;
public interface UserDao {
User findById(Integer uid);
}
2.1.4 创建UserDao.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.atguigu.dao.UserDao">
<select id="findById" resultType="user">
select * from user where id=#{id}
</select>
</mapper>
2.1.5 测试
package com.atguigu;
import com.atguigu.dao.OrdersDao;
import com.atguigu.dao.UserDao;
import com.atguigu.pojo.Orders;
import com.atguigu.pojo.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
// ctrl + alt + f :抽取成员变量
private SqlSession sqlSession;
private InputStream is;
private UserDao userDao;
private OrdersDao orderDao;
/**
* 结束最后执行
*/
@After
public void after() throws Exception{
//提交事务
sqlSession.commit();
//6.释放资源
sqlSession.close();
is.close();
}
/**
* 开始
*/
@Before
public void before() throws Exception{
//
// 1 需要找到核心配置文件
// ctrl + p : 表示查看参数
is = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2 构建会话工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 3 读取核心配置文件里面的io流
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
// 4 获取会话对象
sqlSession = sqlSessionFactory.openSession();
// 5 通过会话工厂,获取userdao对象
userDao = sqlSession.getMapper(UserDao.class);
orderDao = sqlSession.getMapper(OrdersDao.class);
}
@Test
public void testFindAll(){
List<Orders> ordersList = orderDao.findAll();
}
}
运行结果
开启Mybatis的延迟加载策略
我们需要在Mybatis的配置文件SqlMaoConfig.xml文件中添加延迟加载的配置
<!-- logImpl:表示日志的具体实现
STDOUT:标准输出
LOGGING:日志
lazyLoadingEnabled:表示懒加载,用的时候加载,不用的时候不加载
-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
测试结果
我们发现,因为本次只是将 订单对象查询出来放入 List 集合中,并没有涉及到 User对象,所以就没有
发出 SQL 语句查询账户所关联的 User 对象的查询。
查询user对象 测试结果
3.Mybatis缓存
创建项目mybatis_cache
像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提
高性能。
证明一级缓存的存在
一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。
3.1 编写用户持久层UserDao 接口
package com.atguigu.dao;
import com.atguigu.pojo.User;
public interface UserDao {
User findUserById(Integer id);
}
3.2 编写用户持久层映射文件UserDao.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.atguigu.dao.UserDao">
<select id="findUserById" parameterType="int" resultType="user">
select * from user where id=#{id}
</select>
</mapper>
3.3 编写测试方法
package com.atguigu;
import com.atguigu.dao.UserDao;
import com.atguigu.pojo.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
public class MybatisTest {
// ctrl + alt + f :抽取成员变量
private SqlSession sqlSession;
private InputStream is;
private UserDao userDao;
private SqlSessionFactory sqlSessionFactory;
/**
* 结束最后执行
*/
@After
public void after() throws Exception{
//提交事务
// sqlSession.commit();
// 释放资源
// sqlSession.close();
// is.close();
}
/**
* 开始
*/
@Before
public void before() throws Exception{
//
// 1 需要找到核心配置文件
// ctrl + p : 表示查看参数
is = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2 构建会话工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 3 读取核心配置文件里面的io流
sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
// 4 获取会话对象
sqlSession = sqlSessionFactory.openSession();
// // 5 通过会话工厂,获取userdao对象
userDao = sqlSession.getMapper(UserDao.class);
}
/**
* 一级缓存 SqlSession缓存 是mybatis自动开启
* 二级缓存 sqlSessionFactory
* @throws Exception
*/
@Test
public void demo01() throws Exception{
// 根据id进行查询,查询完成之后,自动会把数据丢到sqlsession缓存里面 这个被称为1级缓存
User user1 = userDao.findUserById(1);
System.out.println("user1 = " + user1); // user1 = com.atguigu.pojo.User@57c758ac
// 清空缓存方法
// sqlSession.clearCache();
User user2 = userDao.findUserById(1);
System.out.println("user2 = " + user2); // user2 = com.atguigu.pojo.User@57c758ac
System.out.println(user1 == user2); // true
}
}
测试结果
我们可以发现,虽然在上面的代码中我们查询了两次,但最后只执行了一次数据库操作,这就是 Mybatis 提
供给我们的一级缓存在起作用了。因为一级缓存的存在,导致第二次查询 id 为 1 的记录时,并没有发出 sql 语句
从数据库中查询数据,而是从一级缓存中查询。
3.4 一级缓存的分析
一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
第一次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,如果没有,从数据库查
询用户信息。
得到用户信息,将用户信息存储到一级缓存中。
如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样
做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,缓存中有,直接从缓存
中获取用户信息。
3.5 二级缓存
首先开启 mybatis 的二级缓存。
sqlSession1 去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中。
如果 SqlSession3 去执行相同 mapper 映射下 sql,执行 commit 提交,将会清空该 mapper 映射下的二
级缓存区域的数据。
sqlSession2 去查询与 sqlSession1 相同的用户信息,首先会去缓存中找是否存在数据,如果存在直接从
缓存中取出数据。
3.5.1第一步:在 SqlMapConfig.xml 文件开启二级缓存
<!--
lazyLoadingEnabled:表示懒加载,用的时候加载,不用的时候不加载
cacheEnabled:表示开启二级缓存,默认情况下,这个值是可以省略的
-->
<settings>
<setting name="lazyLoadingEnabled" value="true"></setting>
<setting name="cacheEnabled" value="true"></setting>
</settings>
3.5.2 第二步:配置UserDao.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.atguigu.dao.UserDao">
<!--开启二级缓存-->
<cache></cache>
<!--useCache="true" 前面已经开启了二级缓存,现在我们需要使用二级缓存-->
<!--User findUserById(Integer id);-->
<select id="findUserById" parameterType="int" resultType="user" useCache="true">
select * from user where id=#{id}
</select>
</mapper>
3.5.3测试
/**
* 演示二级缓存 默认情况下 没有开启二级缓存 必须手动开启二级缓存
* 开启二级缓存 只会查询一次结果
* 二级缓存 sqlSessionFactory
* @throws Exception
*/
@Test
public void demo02(){
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserDao dao1 = sqlSession1.getMapper(UserDao.class);
User user1 = dao1.findUserById(1);
System.out.println("user1:=========>" + user1);
sqlSession1.close();//一级缓存消失
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserDao dao2 = sqlSession2.getMapper(UserDao.class);
User user2 = dao2.findUserById(1);
System.out.println("user2:=========>" + user2);
sqlSession2.close();
System.out.println(user1 == user2);
}
3.5.4测试结果
经过上面的测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了一级缓存,再去执行第二
次查询时,我们发现并没有对数据库发出 sql 语句,所以此时的数据就只能是来自于我们所说的二级缓存。
4.Mybatis的注解开发
4.1 Mybatis的常用注解
我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
4.2 Mybatis的增删改查
我们完成简单的user表的增删改查的操作
4.2.1 创建项目 mybatis_anno
4.2.2 添加pom文件
<dependencies>
<!--导入MySQL的驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!--导入MyBatis的jar包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
4.2.3添加sqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<!--
核心配置文件
表示dtd的约束文件
约束文件的意思:所有的配置都需要放到configuration里面,这个里面需要设置各种属性,大概有十个属性,每个属性是有先后顺序,不能随意放置
所以他的名字叫约束文件
-->
<configuration>
<!-- 设置数据源的属性-->
<properties resource="jdbc.properties"></properties>
<!-- logImpl:表示日志的具体实现
STDOUT:标准输出
LOGGING:日志
lazyLoadingEnabled:表示懒加载,用的时候加载,不用的时候不加载
cacheEnabled:表示开启二级缓存,默认情况下,这个值是可以省略的
-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 设置别名-->
<typeAliases>
<!-- 在别名里面设置包名,mybatis会自动的在pojo里面去找他需要的javabean-->
<package name="com.atguigu.pojo"/>
</typeAliases>
<!--
数据源 事物管理器
-->
<!--配置环境变量
environments : 表示设置环境变量,但是环境变量可以设置多个
environment : 表示环境变量
id :表示唯一标示符,随便取名字,想叫什么都可以
default : 表示默认选中哪个环境变量, 注意: 必须跟下面的id保持一致
transactionManager : 表示事物管理器
type="JDBC" : 表示使用JDBC的事物管理器mybatis实际上是对JDBC的封装
MANAGED : 我们自己管理事物
dataSource :表示数据源
type="POOLED" : 表示数据库的连接池
数据源里面需要设置四个参数
驱动,url地址,用户名,密码
UNPOOLED :不适用数据库连接池
JNDI : 只可以跟EJB一起使用
-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--当前的版本 8.0以上,需要设置cj,如果在8.0以下,去掉cj-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
<!--设置URL地址
/// : 这个是主机和端口的缩写
localhost:3306
需要设置时区
北京:东八区,每15度一个区,一个区间隔一个小时
北回归线,广东,广西,云南
时区必须得写,其他的参数可写可不写
useUnicode=true :使用编码格式
characterEncoding=UTF-8 : 编码格式是UTF-8
& :链接符,转义字符 &
get请求:第一个参数 ? 第二个参数:&符号
serverTimezone=Asia/Shanghai ; 使用亚洲上海时区
不要使用UTC
allowPublicKeyRetrieval=true :使用秘钥,使用公钥,只有mysql8.0以上才有
-->
<property name="url" value="jdbc:mysql:///mybatis2?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"></property>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 表示使用配置文件的方式加载crud-->
<!-- <mapper resource="com/atguigu/dao/UserDao.xml"></mapper>-->
<!-- <mapper resource="com/atguigu/dao/OrdersDao.xml"></mapper>-->
<package name="com.atguigu.dao"/>
</mappers>
</configuration>
4.2.4 添加User
package com.atguigu.pojo;
import java.util.Date;
import java.util.List;
public class User {
private Integer id;
private String username;
private String password;
private Date birthday;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", birthday=" + birthday +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
4.2.5 添加UserDao.java
package com.atguigu.dao;
import com.atguigu.pojo.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserDao {
/**
* 插入数据
*/
@Insert("insert into user(username, password, birthday) values(#{username}, #{password}, #{birthday})")
void save(User user);
/**
* 更新数据
* @param user
*/
@Update("update user set username=#{username},password=#{password},birthday=#{birthday} where id=#{id}")
void update(User user);
/**
* 删除数据
* @param id
*/
@Delete("delete from user where id=#{id}")
void deleteById(Integer id);
/**
* 根据id进行查询
* @param id
* @return
*/
@Select("select * from user where id=#{id}")
User findUserById(Integer id);
/**
* 查询所有
* @return
*/
@Select("select * from user")
List<User> findAll();
}
4.2.6 添加测试类MyBatisTest
package com.atguigu;
import com.atguigu.dao.OrderDao;
import com.atguigu.dao.UserDao;
import com.atguigu.pojo.Order;
import com.atguigu.pojo.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MybatisTest {
// ctrl + alt + f :抽取成员变量
private SqlSession sqlSession;
private InputStream is;
private UserDao userDao;
private SqlSessionFactory sqlSessionFactory;
private OrderDao orderDao;
/**
* 结束最后执行
*/
@After
public void after() throws Exception{
//提交事务
sqlSession.commit();
//6.释放资源
sqlSession.close();
is.close();
}
/**
* 开始
*/
@Before
public void before() throws Exception{
//
// 1 需要找到核心配置文件
// ctrl + p : 表示查看参数
is = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2 构建会话工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 3 读取核心配置文件里面的io流
sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
// 4 获取会话对象
sqlSession = sqlSessionFactory.openSession();
// // 5 通过会话工厂,获取userdao对象
userDao = sqlSession.getMapper(UserDao.class);
orderDao = sqlSession.getMapper(OrderDao.class);
}
@Test
public void testFindAll(){
List<User> userList = userDao.findAll();
for (User user : userList) {
System.out.println("user = " + user);
}
}
@Test
public void testFindUserById(){
User user = userDao.findUserById(1);
System.out.println("user = " + user);
}
@Test
public void testDelete(){
userDao.deleteById(5);
}
@Test
public void testUpdate(){
User user = new User();
user.setId(1);
user.setUsername("qweqwe");
user.setPassword("123123");
userDao.update(user);
}
@Test
public void testInsert(){
User user = new User();
user.setUsername("abc");
user.setPassword("123123");
user.setBirthday(new Date());
userDao.save(user);
}
}
修改MyBatis的核心配置文件,我们使用了注解替代的映射文件,所以我们只需要加载使用了注解的Mapper接口即可
<mappers>
<!--扫描使用注解的类-->
<mapper class="com.atguigu.dao.UserDao"></mapper>
</mappers>
或者指定扫描包含映射关系的接口所在的包也可以
<mappers>
<!--扫描使用注解的类所在的包-->
<package name="com.atguigu.dao"></package>
</mappers>
4.3 Mybatis的注解实现复杂映射开发
实现复杂关系映射之前我们可以在映射文件中通过配置 来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置
4.4 一对一查询
4.4.1 一对一查询的模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户
4.4.2 一对一查询的语句
对应的sql语句:
select * from orders;
select * from user where id=查询出订单的uid;
查询的结果如下:
4.4.3 创建Order实体
package com.atguigu.pojo;
import java.io.Serializable;
import java.util.Date;
public class Order implements Serializable {
private int id;
private Date ordertime;
private double total;
// 代表当前订单从属于哪一个客户
private User user;
@Override
public String toString() {
return "Order{" +
"id=" + id +
", ordertime=" + ordertime +
", total=" + total +
", user=" + user +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getOrdertime() {
return ordertime;
}
public void setOrdertime(Date ordertime) {
this.ordertime = ordertime;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
4.4.4 创建OrderDao接口
package com.atguigu.dao;
import com.atguigu.pojo.Order;
import com.atguigu.pojo.User;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface OrderDao {
/**
* 第二种实现方式,根据订单查询用户
* 第二种实现方式 使用懒加载的方式 查询多次
* 第一次先查询订单 在根据订单里面的uid 查询用户对象
*
* column:表示列名
* property:表示属性
* javaType:查询出来的结果 使用哪个对象进行接收
* one:表示查询一的一方
* @return
*/
@Select("select * from orders")
@Results({
@Result(column = "id",property = "id"),
@Result(column = "ordertime", property = "ordertime"),
@Result(column = "total", property = "total"),
@Result(
column = "uid",
property = "user",
javaType = User.class,
one = @One(select = "com.atguigu.dao.UserDao.findUserById")
)
})
List<Order> findAll();
/**
* 第一种实现方式
* 需求:查询订单的时候 查询对应的用户
* 1 查询订单 订单里面有一个用户uid
* 2 根据uid 查询用户对象
* @Results: 表示结果的集合 替代了ResultMap
* @Result:表示结果 替代了id和result
* @return
*/
/* @Select("select * from orders o, user u where o.uid=u.id")
@Results({
@Result(column = "id", property = "id"),
@Result(column = "ordertime", property = "ordertime"),
@Result(column = "total", property = "total"),
@Result(column = "uid", property = "user.id"),
@Result(column = "username", property = "user.username"),
@Result(column = "password", property = "user.password")
})
List<Order> findAll();*/
}
4.4.5 测试结果
@Test
public void testFindOrderAll(){
List<Order> orderList = orderDao.findAll();
for (Order order : orderList) {
System.out.println(order);
}
}
4.5 一对多查询
4.5.1 一对多查询的模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单
4.5.2 一对多查询的语句
对应的sql语句:
select * from user;
select * from orders where uid=查询出用户的id;
查询的结果如下:
4.5.3 修改User实体
public class Order {
private int id;
private Date ordertime;
private double total;
//代表当前订单从属于哪一个客户
private User user;
}
public class User {
private int id;
private String username;
private String password;
private Date birthday;
//代表当前用户具备哪些订单
private List<Order> orderList;
}
4.5.4 UserDaohe和OrderDao接口添加方法
/**
* 根据用户,查询用户所有的订单
* @return
*/
@Select("select * from user")
@Results({
@Result(column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "password",property = "password"),
@Result(
property = "orderList",
column = "id",
javaType = List.class,
many = @Many(select = "com.atguigu.dao.OrderDao.findById")
)
})
List<User> findAllUserAndOrder();
/**
* 插入数据
*/
@Insert("insert into user(username, password, birthday) values(#{username}, #{password}, #{birthday})")
void save(User user);
@Select("select * from orders where uid=#{id}")
List<Order> findById(Integer id);
4.5.5 测试结果
@Test
public void testFindAllUserAndOrder(){
List<User> userList = userDao.findAllUserAndOrder();
for (User user : userList) {
System.out.println(user);
}
}
4.6 多对多查询
4.6.1 多对多查询的模型
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求:查询用户同时查询出该用户的所有角色
4.6.2 多对多查询的语句
对应的sql语句:
select * from user;
select * from role r,user_role ur where r.id=ur.role_id and ur.user_id=用户的id
查询的结果如下:
4.6.3 创建Role实体 修改User实体
public class User {
private int id;
private String username;
private String password;
private Date birthday;
//代表当前用户具备哪些订单
private List<Order> orderList;
//代表当前用户具备哪些角色
private List<Role> roleList;
}
public class Role {
private int id;
private String rolename;
}
4.6.4 添加UserDao接口方法
/**
* 查询用户的时候,查询角色
* @Result: 替代id和result
* id = true: 表示主键id
* javaType = List.class 注意:在注解里面,没有ofType这个属性 不管是一的一方 还是多的一方 全部使用javaType
* 如果是一的一方 直接使用具体的对象Role.class 或 Order.class
* 如果是多的一方 直接使用List.class
* @return
*/
@Select("select * from user")
@Results({
@Result(id = true,column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "password", property = "password"),
@Result(
property = "roleList",
column = "id",
javaType = List.class,
many = @Many(select = "com.atguigu.dao.RoleDao.findById")
)
})
List<User> findUserAndRole();
4.6.5 创建RoleDao接口
package com.atguigu.dao;
import com.atguigu.pojo.Role;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface RoleDao {
@Select("select * from sys_user_role ur,sys_role r where ur.roleid = r.id and ur.userid=#{uid}")
List<Role> findById(Integer id);
}
4.6.6 测试结果
@Test
public void testFindUserAndRole(){
List<User> userList = userDao.findUserAndRole();
for (User user : userList) {
System.out.println(user);
}
}