做网站图片表情,饮料网站建设规划书,wordpress vip system,一个网站需要多少钱mybatis高级查询【掌握】
1、准备工作
【1】包结构
创建java项目#xff0c;导入jar包和log4j日志配置文件以及连接数据库的配置文件#xff1b; 【2】导入SQL脚本
运行资料中的sql脚本#xff1a;mybatis.sql 【3】创建实体来包#xff0c;导入资料中的pojo 【4】User…mybatis高级查询【掌握】
1、准备工作
【1】包结构
创建java项目导入jar包和log4j日志配置文件以及连接数据库的配置文件 【2】导入SQL脚本
运行资料中的sql脚本mybatis.sql 【3】创建实体来包导入资料中的pojo 【4】UserMapper接口
package com.itheima.sh.dao;
import com.itheima.sh.pojo.User;
public interface UserMapper {//完成根据id查询用户数据User selectById(Long id);
}【5】UserMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.heima.mybatis.mapper.UserMapper!--根据id查询:statement--select idselectById resultTypeUserSELECT * FROM tb_user WHERE id#{id}/select/mapper【6】测试
package com.itheima.sh.test;import com.itheima.sh.dao.UserMapper;
import com.itheima.sh.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.BeforeClass;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;public class MybatisTest01 {private static UserMapper mapper null;BeforeClasspublic static void beforeClass() throws Exception {//1.构建SessionFactoryString resouce mybatis-config.xml;InputStream is Resources.getResourceAsStream(resouce);SqlSessionFactory build new SqlSessionFactoryBuilder().build(is);//2.获取sessionSqlSession sqlSession build.openSession(true);//3.获取接口对象mapper sqlSession.getMapper(UserMapper.class);}Testpublic void selectById() {User user mapper.selectById(1L);System.out.println(user);}
}2、表介绍和表关系说明
导入资料中mybatis.sql脚本。新建以下4张表
tb_user用户表
tb_order订单表
tb_item商品表
tb_orderdetail订单详情表【表关系】
1.tb_user和 tb_order表关系tb_user 《》 tb_order一对多 一个人可以下多个订单tb_order 《》 tb_user一对一一个订单只能属于一个人结论tb_user和tb_order属于一对多的关系需要将一方tb_user的主键作为多方tb_order的外键维护关系
2.tb_order 和 tb_item 表关系tb_order 《》 tb_item 一个订单可以有多个商品tb_item 《》 tb_order一个商品可以在多个订单上结论tb_order和tb_item属于多对多的关系需要创建中间表tb_orderdetail维护两个表的关系并且将两张表 的主键作为中间表的外键3、一对一查询
需求通过订单编号20140921003查询出订单信息并查询出下单人信息。
【实现关联查询】
【目标】使用多表关联查询完成根据订单号查询订单信息和下单人信息订单号20140921003
【分析】
一个订单编号对应一个订单一个订单只能属于一个人。所以上述需求实现是一对一的实现。
【步骤】
1、首先编写接口方法。编写SQL语句
2、第二步分析SQL封装数据关联对象
3、处理多表之间的数据封装数据库字段名---》实体类的属性名之间的映射【实现】
第一步需求分析
编写多表关联查询SQL根据订单号查询订单信息及下单人信息
查询语句以及查询结果 #方式一分步查询#第一步根据order_number查询订单信息SELECT * FROM tb_order WHERE order_number 20140921003;#第二步根据订单信息中的user_id查询出下单人的信息SELECT * FROM tb_user WHERE id 1;#方式二多表关联查询内连接SELECT * FROM tb_order tbo inner join tb_user tbu on tbo.user_id tbu.id where tbo.order_number20140921003#多表数据封装问题#关联对象封装数据(在Order中引用User)第二步添加关联
修改Order
在Order类中添加关联对象User并添加getter和setter方法
package com.itheima.sh.pojo;
/*** 订单表* */
public class Order {private Integer id;private String orderNumber;//关联User对象private User user;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getOrderNumber() {return orderNumber;}public void setOrderNumber(String orderNumber) {this.orderNumber orderNumber;}public User getUser() {return user;}public void setUser(User user) {this.user user;}Overridepublic String toString() {return Order{ id id , orderNumber orderNumber \ , user user };}
}第三步添加方法
编写OrderMapper接口 public interface OrderMapper {/*** 根据订单号查询订单及下单人的信息方式二* param orderNumber* return*/Order queryOrderAndUserByOrderNumber2(Param(orderNumber)String orderNumber);
}
第四步编写SQL
在OrderMapper.xml中编写对应的SQL并将OrderMapper.xml加入到mybatis-config.xml全局配置中
【OrderMapper.xml代码】
说明
association配置关联对象User的映射关系association propertyuser javaTypeUser autoMappingtrue/association属性property关联对象在主表实体类中的属性名propertyuser 表示在Order类中的引用的User类的对象 成员变量名javaType关联对象的类型javaTypeUser 表示引用的user对象属于User类型?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
!--
映射文件
namespace 指定接口的类全名
--
mapper namespacecom.itheima.sh.dao.OrderMapper!--1.autoMappingtrue 表示只需要给当前表的id然后自动映射当前表的其他列值到对应实体类的属性中这属于偷懒行为开发中我们最好都书写出来2.id标签表示id的映射关系3.result标签表示其他列和pojo类的属性映射关系4.一对一映射关系使用子标签association来表示引用的另一个pojo类的对象--resultMap idorderAndUserResultRelative typeOrder autoMappingtrue!--主表主键--id columnid propertyid/!--关联关系--!--1.propertyuser 表示在Order类中的引用的User类的对象成员变量名2.javaTypeUser 表示引用的user对象属于User类型--association propertyuser javaTypeUser autoMappingtrue!--从表主键--id columnid propertyid/!--result columnuser_name propertyuserName/--/association/resultMap!--多表关联查询一对一--select idqueryOrderAndUserByOrderNumber2 resultMaporderAndUserResultRelativeSELECT*FROMtb_order tboINNER JOIN tb_user tbu ON tbo.user_id tbu.idWHEREtbo.order_number #{orderNumber}/select
/mapper说明
1、由于queryOrderAndUserByOrderNumber2查询的结果Order对象中需要封装User信息所以返回值不能够再使用单纯的resultType来操作2、定义resultMap进行关联查询的配置其中属性id标识这个resultMaptype返回的结果类型autoMappingtrue 表示只需要给当前表的id然后自动映射当前表的其他列值到对应实体类的属性中这 属于偷懒行为开发中我们最好都书写出来子元素id主表主键映射result主表普通字段的映射association:关联对象的映射配置3、association配置关联对象User的映射关系属性property关联对象在主表实体类中的属性名propertyuser 表示在Order类中的引用的User类的对象 成员变量名javaType关联对象的类型javaTypeUser 表示引用的user对象属于User类型第五步测试
package com.itheima.sh.test;import com.itheima.sh.dao.OrderMapper;
import com.itheima.sh.dao.UserMapper;
import com.itheima.sh.pojo.Order;
import com.itheima.sh.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.BeforeClass;
import org.junit.Test;
import java.io.InputStream;
public class MybatisTest02 {private static OrderMapper mapper null;BeforeClasspublic static void beforeClass() throws Exception {//1.构建SessionFactoryString resouce mybatis-config.xml;InputStream is Resources.getResourceAsStream(resouce);SqlSessionFactory build new SqlSessionFactoryBuilder().build(is);//2.获取sessionSqlSession sqlSession build.openSession(true);//3.获取接口对象mapper sqlSession.getMapper(OrderMapper.class);}Testpublic void selectById() {Order order mapper.queryOrderAndUserByOrderNumber2(20140921003);System.out.println(order order);}
}【测试结果】 注意事项
通过上述测试结果我们发现User的id是错误的不是3正确结果是1 因为tb_user表的主键是idtb_order的主键也是id。查询的结果中有两列相同的id字段。在将查询结果封装到实体类的过程中就会封装错误。
注意user表查询的是id不是id1,由于SQLyog图形化界面显示的原因。可以在cmd窗口查看结果 【解决方案】
1、建议将所要查询的所有字段显示地写出来
2、将多表关联查询结果中相同的字段名取不同的别名resultMap中应该如下配置 【正确结果】 【小结】
一对一关联查询
1、需要在Order实体类中关联User对象最终将数据封装到Order中
2、在OrderMapper.xml文件中书写关联语句并配置关系
3、关联关系配置resultMap idorderAndUserResultRelative typeOrder autoMappingtrue!--主表主键--id columnoid propertyid/!--关联关系--association propertyuser javaTypeUser autoMappingtrue!--从表主键--id columnuid propertyid//association/resultMap4、一对多查询
【目标】查询id为1的用户及其订单信息
【分析】
一个用户可以有多个订单。
一个订单只能属于一个用户。
用户(1)-----订单(n)
【步骤】
第一步查询SQL分析
第二步添加关联关系
第三步编写接口方法
第四步编写映射文件
第五步测试【实现】
第一步需求分析
编写SQL实现查询id为1的用户及其订单信息
查询语句及查询结果 #查询id为1的用户及其订单信息
select * from tb_user where id1;
select * from tb_order where user_id1;#一对多 内连接查询
select * from tb_user tbu inner join tb_order tbo on tbu.id tbo.user_id where tbu.id1;
# 封装数据关联对象一个用户关联多个订单 User(ListOrder orderList)说明一个用户关联多个订单 User(List orderList) 在User类中定义一个List集合存储多个订单Order对象。
第二步添加映射关系
因为一个用户可以拥有多个订单所以用户和订单是一对多的关系需要在User类中添加一个ListOrder 属性
package com.itheima.sh.pojo;import java.io.Serializable;
import java.util.List;public class User implements Serializable {private Long id;// 用户名private String userName;// 密码private String password;// 姓名private String name;// 年龄private Integer age;//0 女性 1 男性private Integer sex;//订单ListOrder orders;public Long getId() {return id;}public void setId(Long 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 String getName() {return name;}public void setName(String name) {this.name name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age age;}public Integer getSex() {return sex;}public void setSex(Integer sex) {this.sex sex;}public ListOrder getOrders() {return orders;}public void setOrders(ListOrder orders) {this.orders orders;}Overridepublic String toString() {return User{ id id , userName userName \ , password password \ , name name \ , age age , sex sex , orders orders };}
}
第三步编写接口方法
在UserMapper接口中添加关联查询 /*** 根据用户id查询用户及其订单信息* param id* return*/User oneToManyQuery(Param(id) Long id);第四步编写SQL
在UserMapper.xml文件中编写SQL语句完成一对多的关联查询
说明
1.一对多使用collection子标签进行关联多方Ordercollection property类中引用多方的成员变量名 javaType存放多方容器的类型 ofType多方类型 autoMappingtrue/collection
2.属性1propertyorders 这里的orders表示User类的成员变量orders2javaTypeList 表示User类的成员变量orders存储的Order对象使用的类型这里是List 一般不书写3) ofTypeOrder 表示List集合中存储数据的类型 Order
3.一定要记住这里给user表的id起别名是uid,order表的id起别名是oid.在resultMap标签的id子标签中的column属性值书写对应的uid和oid.!--自定义结果集--resultMap idoneToManyResult typeUser autoMappingtrue!--User的主键--id columnuid propertyid/!--Order关联映射--!--1.一对多使用collection子标签进行关联多方Order2.属性1propertyorders 这里的orders表示User类的成员变量orders2javaTypeList 表示User类的成员变量orders存储的Order对象使用的类型这里是List可以不配置3) ofTypeOrder 表示List集合中存储数据的类型 Order--collection propertyorders javaTypeList ofTypeOrder autoMappingtrue!--Order的主键--id columnoid propertyid //collection/resultMap!--根据用户ID查询用户及其订单数据--select idoneToManyQuery resultMaponeToManyResultSELECTtbo.id as oid,tbo.order_number,tbu.id as uid,tbu.user_name,tbu.password,tbu.name,tbu.age,tbu.sexFROMtb_user tbuINNER JOIN tb_order tbo ON tbu.id tbo.user_idWHEREtbu.id #{id}/select第五步测试
在用户的测试类中
public class MybatisTest01 {private static UserMapper mapper null;BeforeClasspublic static void beforeClass() throws Exception {//1.构建SessionFactoryString resouce mybatis-config.xml;InputStream is Resources.getResourceAsStream(resouce);SqlSessionFactory build new SqlSessionFactoryBuilder().build(is);//2.获取sessionSqlSession sqlSession build.openSession(true);//3.获取接口对象mapper sqlSession.getMapper(UserMapper.class);} //根据用户ID查询用户及其订单数据Testpublic void oneToManyQuery() {User user mapper.oneToManyQuery(1L);System.out.println(user user);}
}【小结】
一对多关系配置
1、在对象中添加映射关系
2、编写接口方法编写SQL
3、编写resultMap处理数据库字段和实体类之间数据的封装5、多对多
【需求】查询订单号为20140921001的订单的详情信息即查询订单信息订单中的商品信息
【步骤】
第一步需求分析
第二步添加关联关系
第三步编写SQL
第四步配置关联关系
第五步运行第一步【需求分析】 1、查询订单详情信息即查询订单信息订单中的商品信息
2、订单信息在tb_order中订单中的商品信息在tb_item中这两个表是通过中间表 tb_orderdetail进行关联的。
3、关联查询思路先查询订单表通过订单表中的id关联中间表order_id,然后查询中间表根据中间表的item_id关联商品表的id,最后查询商品表【SQL查询及结果】 # 【需求】查询订单号为20140921001的订单的详情信息 订单的详情信息 订单商品
SELECT*
FROMtb_order tbo
INNER JOIN tb_orderdetail detail ON tbo.id detail.order_id
INNER JOIN tb_item item ON detail.item_id item.id
WHERE
tbo.order_number 20140921001;第二步添加关联关系
【修改Order】
一个订单表中关联了多个订单详情信息所以在订单表中添加ListOrderdetail属性
【Order.java】
package com.itheima.sh.pojo;
import java.util.List;
/*** 订单表* */
public class Order {private Integer id;private String orderNumber;//关联User对象private User user;//关联订单详情列表private ListOrderdetail detailList;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getOrderNumber() {return orderNumber;}public void setOrderNumber(String orderNumber) {this.orderNumber orderNumber;}public User getUser() {return user;}public void setUser(User user) {this.user user;}public ListOrderdetail getDetailList() {return detailList;}public void setDetailList(ListOrderdetail detailList) {this.detailList detailList;}Overridepublic String toString() {return Order{ id id , orderNumber orderNumber \ , user user , detailList detailList };}
}【修改Orderdetail】
每一条订单详情记录中都包含了一条商品信息所以需要在Orderdetail中添加一个Item属性
【Orderdetail.java】
package com.itheima.sh.pojo;
public class Orderdetail { private Integer id; private Double totalPrice; private Integer status;//商品信息private Item item;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public Double getTotalPrice() {return totalPrice;}public void setTotalPrice(Double totalPrice) {this.totalPrice totalPrice;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status status;}public Item getItem() {return item;}public void setItem(Item item) {this.item item;}Overridepublic String toString() {return Orderdetail{ id id , totalPrice totalPrice , status status , item item };}
}第三步编写接口方法
在OrderMapper接口中新增根据orderNumber查询订单及订单详情的方法
public interface OrderMapper {/*** 根据orderNumber查询订单及其详情信息* param orderNumber* return*/Order queryOrderAndDetailByOrderNumber(Param(orderNumber) String orderNumber);
}第四步编写SQL
说明一定要记住这里给order表的id起别名是oid,订单详情表的id起别名是detailId商品表item的id起别名是itemId。在resultMap标签的id子标签中的column属性值书写对应的oid、detailId和itemId. !--订单及订单详情结果集--resultMap idorderAndDetailMap typeOrder autoMappingtrue!--tb_order表 和 Order实体类--!--订单表主键--id propertyid columnoid/!--多个订单详情 1对多detailList--collection propertydetailList javaTypeList ofTypeOrderdetail autoMappingtrue!--tb_order_detail表 和 Orderdetail实体类--!--订单详情主键 detailId表示下面sql语句的别名--id propertyid columndetailId/!--关联商品对象 一对一orderdetail-Item--association propertyitem javaTypeItem autoMappingtrue!--tb_item表 和 Item实体类 itemId 表示下面的sql语句别名--id propertyid columnitemId//association/collection/resultMap!--多对多查询--select idqueryOrderAndDetailByOrderNumber resultMaporderAndDetailMapSELECTtbo.id as oid,tbo.order_number,detail.id as detailId,detail.total_price,detail.status,item.id as itemId,item.item_detail,item.item_name,item.item_priceFROMtb_order tboINNER JOIN tb_orderdetail detail ON tbo.id detail.order_idINNER JOIN tb_item item ON detail.item_id item.idWHEREtbo.order_number #{orderNumber};/select第五步测试 Testpublic void queryOrderAndDetailByOrderNumber() {Order order mapper.queryOrderAndDetailByOrderNumber(20140921001);System.out.println(order order);}【结果】 【扩展】
【需求】根据订单号20140921001
查询订单信息
查询订单所属用户信息
查询订单中的详细商品信息 【SQL实现及查询结果】
通过分析实现这个查询就在上面的查询基础上再关联一个一对一的User信息 #查询订单详情
SELECTtbo.id as oid,tbo.order_number,detail.id as detailId,detail.total_price,detail.status,item.id as itemId,item.item_detail,item.item_name,item.item_price,tbu.id as uid,tbu.age,tbu.name,tbu.password,tbu.sex,tbu.user_name
FROMtb_order tbo
INNER JOIN tb_orderdetail detail ON tbo.id detail.order_id
INNER JOIN tb_item item ON detail.item_id item.id
INNER JOIN tb_user tbu ON tbo.user_id tbu.id
WHERE
tbo.order_number 20140921001;【添加关联关系】
都已经在实体类添加完毕直接操作即可
【编写接口方法】
在OrderMapper接口中再扩展一个方法queryOrderAndDetailAndUserByOrderNumber /*** 根据orderNumber查询 订单详情商品及用户数据* param orderNumber* return*/Order queryOrderAndDetailAndUserByOrderNumber(Param(orderNumber) String orderNumber);【编写SQL】 !--订单及订单详情结果集--resultMap idorderAndDetailMapPlus typeOrder autoMappingtrue!--tb_order表 和 Order实体类--!--订单表主键--id propertyid columnoid/!--Order-User一对一关联--association propertyuser javaTypeUser autoMappingtrue!--User主键--id propertyid columnuid//association!--多个订单详情 1对多detailList--collection propertydetailList javaTypeList ofTypeOrderdetail autoMappingtrue!--tb_order_detail表 和 Orderdetail实体类--!--订单详情主键--id propertyid columndetailId/!--关联商品对象 一对一orderdetail-Item--association propertyitem javaTypeItem autoMappingtrue!--tb_item表 和 Item实体类--id propertyid columnitemId//association/collection/resultMapselect idqueryOrderAndDetailAndUserByOrderNumber resultMaporderAndDetailMapPlusSELECTtbo.id as oid,tbo.order_number,detail.id as detailId,detail.total_price,detail.status,item.id as itemId,item.item_detail,item.item_name,item.item_price,tbu.id as uid,tbu.age,tbu.name,tbu.password,tbu.sex,tbu.user_nameFROMtb_order tboINNER JOIN tb_orderdetail detail ON tbo.id detail.order_idINNER JOIN tb_item item ON detail.item_id item.idINNER JOIN tb_user tbu ON tbo.user_id tbu.idWHEREtbo.order_number #{orderNumber};/select【测试】 【结果】 6、ResultMap继承
如果两个结果集有重叠的部分如下图所示。我们可以使用结果集继承来实现重叠的结果集的复用。 orderAndDetailAndUserMap结果集可以继承orderAndDetailMap结果集。 7、高级查询小结
resutlType无法帮助我们自动的去完成映射所以只有使用resultMap手动的进行映射
resultMap: 属性type 结果集对应的数据类型 Orderid 唯一标识被引用的时候进行指定autoMapping 开启自动映射extends 继承子标签id:配置id属性result:配置其他属性association配置一对一的映射property 定义对象的属性名javaType 属性的类型autoMapping 开启自动映射collection配置一对多的映射property 定义对象的属性名javaType 集合的类型ofType 集合中的元素类型 泛型autoMapping 开启自动映射