网站平台 生态建设,wordpress rewirte,深圳市外贸公司,北京宣传片简单介绍#xff1a;
在前一章我们介绍了关于MyBatis的多表查询的时候的对应关系#xff0c;其中有三种对应关系#xff0c;分别是一对一#xff0c;一对多#xff0c;多对多的关系。如果忘记了这三种方式的对应形式可以去前面看看#xff0c;一定要记住这三种映射关系的…简单介绍
在前一章我们介绍了关于MyBatis的多表查询的时候的对应关系其中有三种对应关系分别是一对一一对多多对多的关系。如果忘记了这三种方式的对应形式可以去前面看看一定要记住这三种映射关系的图表形式以及在Java中的以类的形式存在的嵌套关系。这次我们来详细的讲解一对一关系的详细使用方法。
在一对一映射关系的查询中需要使用到assciaition元素它提供了一系列的用于维护表与表之间关系的属性
property用于指定映射关系到实体类对象的属性与表字段一一对应
column用于指定表中与对象的属性对应的字段。使用column和property可以完成数据表字段和实体类属性的映射关系。
javaType用于指定映射到实体类属性值的数据类型
jdbcType用于指定数据表中对应字段的类型
fetchType用于指定在关联查询时是否启动延迟加载fatchType有属性有两个值lazy和eager两个属性值默认为lazy。
select用于指定引入嵌套查询的子SQL语句。
typeHandler用于指定一个类处理器
assciaition是resultMap的子元素也就是说要使用这个元素需要手动的指定自定义映射规则并且在我们做多表查询的时候有两种配置方法嵌套查询和嵌套结果集我们先讲解嵌套查询
嵌套查询的方式进行多表查询
嵌套查询的核心理念将一条查询语句的结果当作另一条查询语句的查询条件。比如在我们想要查询学生的学生卡的时候需要首先查询学生的信息得到这个学生的所有信息之后找出学籍号这一列然后用这个数据再去查询学生卡在SQL语句中就是这样的 查询结果就是这样的 而我们要做就是将子查询的查询结果分离出我们要的列的信息之后再把这个信息传递给父查询作为查询参数进行进一步查询最终得出我们想要的结果
前期准备
首先我们需要两个数据库一个用来存储学生的相关信息一个用来存储学生卡的相关信息 SQL语句
show databases ;
use mybatis;
show tables ;
create table user(id int COMMENT id信息,name varchar(10) COMMENT 姓名,sex varbinary(3) COMMENT 性别,id_card int COMMENT id号码
);
# 这两张表使用id_card字段形成一对一的关系
insert into user values (1,张三,男,1),(2,李四,女,2),(3,王五,男,3);
create table id_card(id_card int COMMENT id号码,Information varchar(30) COMMENT 信息
);
insert into id_card values (1,我是张三的信息),(2,我是李四的信息),(3,我是王五的信息);
select * from user;
select * from id_card; 然后就是与之对应的Java实体类我们需要两个类一个学生类用来存储学生的相关信息一个学生卡类用来存储学生的相关信息
首先是学生卡类
package com.mybatis.POJO;public class IdCard {private int id_card;private String Information;public IdCard() {}public IdCard(int id_card, String information) {this.id_card id_card;Information information;}public int getId_card() {return id_card;}public void setId_card(int id_card) {this.id_card id_card;}public String getInformation() {return Information;}public void setInformation(String information) {Information information;}Overridepublic String toString() {return IdCard{ id_card id_card , Information Information \ };}
}然后是学生类
package com.mybatis.POJO;public class User{private int id;private String name;private String sex;private IdCard id_card;public User() {}public User(int id, String name, String sex, IdCard id_card) {this.id id;this.name name;this.sex sex;this.id_card id_card;}public int getId() {return id;}public void setId(int id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex sex;}public IdCard getId_card() {return id_card;}public void setId_card(IdCard id_card) {this.id_card id_card;}Overridepublic String toString() {return User{ id id , name name \ , sex sex \ , id_card id_card };}
} 在创建学生类的时候就需要注意了在我们之前介绍一对一查询的Java类实现的时候曾经说过在Java中体现一对一的查询就是在本类中定义与之关联的类的对象做为属性。比如在A类中定义B类对象作为属性在B类中定义A类为属性。形成一种互相包含的属性 关键点在这里 在学生类里面有一个属性它的类型是学生卡类也就是达成了我们之前说过一个类里面包含与之关联的对象作为属性这里是第一个需要注意的点。
使用方法
在我们创建完之前的数据库和实体类之后接下来就是进行我们SQL映射语句的编写了
在我们的嵌套查询的形式中需要将子查询和父查询分开来写也就是需要两条SQL映射语句
!-- 首先是子查询--select idselectIdCard parameterTypeint resultTypeIdCardselect * from id_card where id_card #{id};/select
!-- 然后是父查询--select idselectUser resultMapMapperIdCard parameterTypeintselect * from user where id #{id};/selectresultMap idMapperIdCard typeUserresult columnname propertyname/result columnid propertyid/result columnsex propertysex/association propertyid_cardcolumnid_cardjavaTypeIdCardselectmappers.NestedSelect.selectIdCard//resultMap
我们来解释一下上面的SQL映射文件的片段
最上面的SQL映射语句是子查询也就是对应了我们完整的SQL语句中的这个位置 传递的参数就是int类型就是要根据这个值查询返回的类型是IdCard也就是是这个值 子查询就是由这些组成的然后关键在于夫查询
父查询的SQL语句对应完整的SQL语句如下 SQL语句的传入参数的属性是int类型也就是要根据这个值去查询学生信息然后从学生信息中获取到学生卡号信息再用学生卡号信息去查询学生卡信息具体的参数的流向如下图所示 红色的箭头指向的是参数的传递蓝色的箭头指向的是结果集的封装。那么最后的SQL语句运行结果就是这样的 其中由两个比较重要的问题是我们在之后编写自定义映射规则的时候需要解决的
1.如何从所有的参数中单独拿出id_card列的数据进行传递
2.如何将结果集封装成IdCard属性并传递给学生类
然后我们就要开始对我们之前编写的SQL映射文件中的内容进行详细的解释
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
!-- 接口式开发有两个规范: --
!--1.接口中方法的名称必须与SQL语句的唯一标识,也就是id的值保持一致,resultType就是接口中返回值的类型,parameterType就是接口中方法的参数的类型--
!-- 2.mapper标签的namespace属性必须是接口的全路径,否则在运行的时候会无法找到接口对象的SQL映射文件 --
mapper namespacemappers.NestedSelect!-- 根据id查询单条数据--select idselectOne resultTypeUser parameterTypeintselect *from userwhere id #{id};/select!-- 查询所有的数据--select idselectAll resultTypeUserselect *from user;/select
!-- 开始编写关于嵌套查询的内容--
!-- 首先是子查询--select idselectIdCard parameterTypeint resultTypeIdCardselect * from id_card where id_card #{id};/select
!-- 然后是父查询--select idselectUser resultMapMapperIdCard parameterTypeintselect * from user where id #{id};/selectresultMap idMapperIdCard typeUserresult columnname propertyname/result columnid propertyid/result columnsex propertysex/association propertyid_cardcolumnid_cardjavaTypeIdCardselectmappers.NestedSelect.selectIdCard//resultMap
/mapper 首先我们来看父查询中的resultMap部分 其中在我们的自定义结果集映射的部分前几个部分都是和之前是一样的在最后的association元素中property指向的就是我们的一个类里面包含与之关联的对象作为属性column就是与其他表建立联系的字段这个值也就是我们传递给子查询的参数的来源JavaType的值就是一个类里面包含与之关联的对象作为属性的这个与之关联的对象的类也就是我们的IdCard的类名最后的select指向的就是子查询的SQL语句的唯一标识
具体的参数的传递如下面的图式所示 最终的运行结果就是如下所示 在数据库中的查询语句如下 查询结果如下 代码实现
最后总结一下完整的代码
SQL映射文件
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
!-- 接口式开发有两个规范: --
!--1.接口中方法的名称必须与SQL语句的唯一标识,也就是id的值保持一致,resultType就是接口中返回值的类型,parameterType就是接口中方法的参数的类型--
!-- 2.mapper标签的namespace属性必须是接口的全路径,否则在运行的时候会无法找到接口对象的SQL映射文件 --
mapper namespacemappers.NestedSelect!-- 根据id查询单条数据--select idselectOne resultTypeUser parameterTypeintselect *from userwhere id #{id};/select!-- 查询所有的数据--select idselectAll resultTypeUserselect *from user;/select
!-- 开始编写关于嵌套查询的内容--
!-- 首先是子查询--select idselectIdCard parameterTypeint resultTypeIdCardselect * from id_card where id_card #{id};/select
!-- 然后是父查询--select idselectUser resultMapMapperIdCard parameterTypeintselect * from user where id #{id};/selectresultMap idMapperIdCard typeUserresult columnname propertyname/result columnid propertyid/result columnsex propertysex/association propertyid_cardcolumnid_cardjavaTypeIdCardselectmappers.NestedSelect.selectIdCard//resultMap
/mapper
接口文件
package mappers;import com.mybatis.POJO.IdCard;
import com.mybatis.POJO.User;import java.util.List;public interface NestedSelect {public User selectOne(int i);public ListUser selectAll();public ListUser selectUser(int i);public ListIdCard selectIdCard(int i);
}测试类
package mappers;import Tools.create;
import com.mybatis.POJO.IdCard;
import com.mybatis.POJO.User;
import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;public class NestedSelectTest {NestedSelect mapper null;SqlSession session null;Beforepublic void setUp() throws Exception {session create.createSqlSession();mapper create.createNestedSelectMappers();}Testpublic void testSelectOne() {User user mapper.selectOne(1);System.out.println(user.toString());}Testpublic void testSelectAll() {for (User user : mapper.selectAll()) {System.out.println(user.toString());}}
// 测试嵌套查询的运行语句Testpublic void selectUser(){for (User user : mapper.selectUser(2)) {System.out.println(user.toString());}}Testpublic void selectIdCard(){for (IdCard idCard : mapper.selectIdCard(1)) {System.out.println(idCard.toString());}}
}
运行结果 注意点
在这一章节中所需要的注意点就是我们在配置SQL映射文件的时候一定要清晰的理解这些配置项之间的嵌套关系以及类与类表与表之间的关系或者如果不理解的话至少知道怎么写能出现什么效果。常见的报错就是SQL语句的嵌套关系错误导致的查询结果不正确如果出现了查询结果不正确首先去检查映射关系的部分。如果出现了查询不到数据可以去看看有没有配置之前的驼峰映射这个配置会影响后续的我们的自定义映射关系的数据有可能会导致最终的结果查询不到数据。