MyBatis使用嵌套查詢collection和association的實現(xiàn)
1、目標(biāo)
本文的主要目標(biāo)是MyBatis使用collection標(biāo)簽完成一對多的嵌套查詢,使用association標(biāo)簽完成一對一的嵌套查詢
2、一對多的嵌套查詢用collection標(biāo)簽
2.1 多表查詢并且resultMap是數(shù)據(jù)庫的class表
create table `class` ( `id` int primary key auto_increment, `name` varchar(100) not null, `create_time` date not null ); create table `stu` ( `id` int primary key auto_increment, `name` varchar(100) not null, `age` int not null, `class_id` int not null );
先在數(shù)據(jù)庫創(chuàng)建表class和stu,class是班級表,stu是學(xué)生表,stu學(xué)生表中包含class_id字段表示這個學(xué)生在哪個班級中
insert into `class`(`name`, `create_time`) values ('1班', now()), ('2班', now()), ('3班', now());
然后在class表中插入記錄
insert into `stu`(`name`, `age`, `class_id`) values ('張三1', 20, 1), ('李四1', 18, 1), ('王五1', 21, 1), ('張三2', 15, 2), ('李四2', 19, 2), ('王五2', 16, 2), ('張三3', 22, 3), ('李四3', 29, 3), ('王五3', 26, 3);
然后在stu表中插入記錄
@Data public class Class { private String id; private String name; private String createTime; private List<Stu> stuList; @Override public String toString() { return "Class{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", createTime='" + createTime + '\'' + ", stuList=" + stuList + '}'; } }
創(chuàng)建Class實體類,對應(yīng)class表的字段,其中多了一個字段是stuList這個list集合,因為一個班級包含了多個學(xué)生,這里是一對多的嵌套查詢因此用collection標(biāo)簽
@Data public class Stu { private Integer id; private String name; private Integer age; private Integer classId; @Override public String toString() { return "Stu{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", classId=" + classId + '}'; } }
創(chuàng)建Stu實體類,對應(yīng)stu表的字段
@Mapper public interface ClassMapper { Class getClass(@Param("className") String className); }
創(chuàng)建ClassMapper的接口方法getClass,入?yún)⑹莄lassName,出參是一個Class班級對象,這個班級對象會封裝多個學(xué)生對象
<?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="org.apache.mybatisDemo.ClassMapper"> <resultMap id="classMap" type="org.apache.mybatisDemo.Class"> <id property="id" column="classId"/> <result property="name" column="className"/> <result property="createTime" column="create_time"/> <collection property="stuList" javaType="java.util.List" ofType="org.apache.mybatisDemo.Stu"> <result property="id" column="stuId"/> <result property="name" column="stuName"/> <result property="age" column="age"/> <result property="classId" column="class_id"/> </collection> </resultMap> <select id="getClass" resultMap="classMap"> select c.id classId, c.name className, c.create_time, s.id stuId, s.name stuName, s.age, s.class_id from `class` c inner join `stu` s on c.id = s.class_id where c.`name` = #{className} </select> </mapper>
sql使用多表查詢,resultMap是返回值的類型,使用collection標(biāo)簽封裝多個Stu學(xué)生對象,collection標(biāo)簽中javaType指定是List集合類型,ofType指定List集合的泛型類型
注意:
(1)
<id property="id" column="classId"/> <result property="name" column="className"/> <result property="createTime" column="create_time"/>
resultMap中除了collection的更新字段至少有1個,比如這里我更新了3個字段
如果除了collection沒有更新字段,會拋出異常,具體參考我寫的博客:MyBatis嵌套查詢collection報錯:org.apache.ibatis.exceptions.TooManyResultsException
(2)sql查詢的字段如果重復(fù)名字的要取別名,如果不取別名resultMap直接用c.id,MyBatis底層不會將這個字段作為查詢字段,因為它識別不了c是哪張表
<mappers> <mapper resource="mybatis/ClassMapper.xml"/> </mappers>
mybatis-config.xml文件中設(shè)置mapper標(biāo)簽是ClassMapper.xml,因此可以掃描到這個xml文件
@Test public void f1() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession sqlSession = sqlSessionFactory.openSession()) { ClassMapper mapper = sqlSession.getMapper(ClassMapper.class); Class cls = mapper.getClass("2班"); System.out.println(cls.toString()); } }
測試這個接口方法
測試結(jié)果返回一個Class班級對象,這個對象包含id=2,name=2班,createTime,stuList是一個list集合,它封裝了多個Stu學(xué)生對象
2.2 多表查詢并且resultMap是自定義VO類ClassVO
那resultMap返回值類型必須是數(shù)據(jù)庫表對應(yīng)的實體類嗎?不一定,返回值類型可以是自定義類比如VO
@Data public class ClassVO { private String id; private List<Stu> stuList; @Override public String toString() { return "ClassVO{" + "id='" + id + '\'' + ", stuList=" + stuList + '}'; } }
自定義VO類ClassVO包含的字段只有id和stuList這個list集合
@Mapper public interface ClassMapper { ClassVO getClassVO(@Param("className") String className); }
創(chuàng)建接口方法,返回值類型是自定義ClassVO類
<?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="org.apache.mybatisDemo.ClassMapper"> <resultMap id="classVOMap" type="org.apache.mybatisDemo.ClassVO"> <id property="id" column="classId"/> <collection property="stuList" javaType="java.util.List" ofType="org.apache.mybatisDemo.Stu"> <id property="id" column="stuId"/> <result property="name" column="stuName"/> <result property="age" column="age"/> <result property="classId" column="class_id"/> </collection> </resultMap> <select id="getClassVO" resultMap="classVOMap"> select c.id classId, c.name, c.create_time, s.id stuId, s.name stuName, s.age, s.class_id from `class` c inner join `stu` s on c.id = s.class_id where c.`name` = #{className} </select> </mapper>
這個接口方法的xml對應(yīng)的返回值類型是type=“org.apache.mybatisDemo.ClassVO”
注意:
(1)resultMap中除了collection的更新字段至少有1個
(2)sql查詢的字段如果重復(fù)名字的要取別名
@Test public void f2()throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession sqlSession = sqlSessionFactory.openSession()) { ClassMapper mapper = sqlSession.getMapper(ClassMapper.class); ClassVO classVO = mapper.getClassVO("2班"); System.out.println(classVO.toString()); } }
測試getClassVO方法,返回值是一個ClassVO對象
測試結(jié)果是返回一個ClassVO對象,它包含id=2,stuList這個list集合,它包含了3個Stu學(xué)生對象
結(jié)論:resultMap返回值類型不一定是數(shù)據(jù)庫表對應(yīng)的實體類,可以是自己定義的類
2.3 單表查詢并且resultMap是自定義VO類ClassVO
可以單表查詢stu學(xué)生表然后resultMap可以映射嗎?可以,不過除了resultMap中除了collection必須至少有1個字段更新
@Mapper public interface ClassMapper { ClassVO getClasVOBySingleTable(@Param("classId") Integer classId); }
創(chuàng)建一個mapper接口方法
<?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="org.apache.mybatisDemo.ClassMapper"> <resultMap id="ClasVOBySingleTableMap" type="org.apache.mybatisDemo.ClassVO"> <id property="id" column="class_id"/> <collection property="stuList" javaType="java.util.List" ofType="org.apache.mybatisDemo.Stu"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="age" column="age"/> <result property="classId" column="class_id"/> </collection> </resultMap> <select id="getClasVOBySingleTable" resultMap="ClasVOBySingleTableMap"> select * from stu where stu.class_id = #{classId} </select> </mapper>
mapper.xml文件中sql是單表查詢,也可以進(jìn)行resultMap的字段賦值
注意:
(1)resultMap中除了collection的更新字段至少有1個
(2)sql查詢的字段如果重復(fù)名字的要取別名
@Test public void f3() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession sqlSession = sqlSessionFactory.openSession()) { ClassMapper mapper = sqlSession.getMapper(ClassMapper.class); ClassVO classVO = mapper.getClasVOBySingleTable(2); System.out.println(classVO.toString()); } }
調(diào)用getClasVOBySingleTable方法會返回ClassVO對象
測試結(jié)果是單表查詢,也可以返回一個ClassVO對象,它包含id=2,stuList是list集合,它包含3個Stu學(xué)生對象
結(jié)論:單表查詢stu學(xué)生表然后resultMap可以映射
2.4 單表查詢并且resultMap是自定義VO類ClassVO,返回值是List類型
@Mapper public interface ClassMapper { List<ClassVO> getClassVOList(); }
mapper接口方法的返回值是list集合
<select id="getClassVOList" resultMap="ClasVOBySingleTableMap"> select * from stu </select>
mapper.xml文件中單表查詢,resultMap仍然是2.3中的resultMap即ClasVOBySingleTableMap,因為返回值類型list集合的泛型還是ClassVO類
@Test public void f4() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession sqlSession = sqlSessionFactory.openSession()) { ClassMapper mapper = sqlSession.getMapper(ClassMapper.class); List<ClassVO> list = mapper.getClassVOList(); list.forEach(System.out::println); } }
測試:調(diào)用getClassVOList方法
測試結(jié)果是單表查詢返回stu學(xué)生表的所有記錄,指定resultMap,封裝了collection,因此會將相同class_id的多個Stu學(xué)生對象封裝到一個ClassVO對象,結(jié)果是返回3個ClassVO對象,每個ClassVO對象都封裝了3個Stu對象
結(jié)論:mapper接口方法的返回值是多個class_id的ClassVO對象用List集合,resultMap指定List集合的泛型,MyBatis會自動將相同class_id的Stu學(xué)生對象封裝到一個ClassVO對象中
2.5 多表查詢并且resultMap是數(shù)據(jù)庫的class表,返回值是List類型
@Mapper public interface ClassMapper { List<Class> getClassList(); }
返回值是List集合
<select id="getClassList" resultMap="classMap"> select c.id classId, c.name className, c.create_time, s.id stuId, s.name stuName, s.age, s.class_id from `class` c inner join `stu` s on c.id = s.class_id </select>
resultMap復(fù)用2.1的resultMap,因為返回值是list集合,它的泛型和2.1的返回值類型是相同的
@Test public void f5() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession sqlSession = sqlSessionFactory.openSession()) { ClassMapper mapper = sqlSession.getMapper(ClassMapper.class); List<Class> list = mapper.getClassList(); list.forEach(System.out::println); } }
調(diào)用getClassList方法
返回值是3個Class班級對象,每個Class班級對象都封裝了自己班的Stu學(xué)生對象
結(jié)論:mapper接口方法的返回值是多個class_id的Class班級對象用List集合,resultMap指定List集合的泛型,MyBatis會自動將相同class_id的Stu學(xué)生對象封裝到一個Class班級對象中
3、一對一的嵌套查詢用association標(biāo)簽
3.1 多表查詢,返回值是Stu學(xué)生對象
@Data public class Stu { private Integer id; private String name; private Integer age; private Integer classId; private Class stuClass; @Override public String toString() { return "Stu{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", classId=" + classId + ", stuClass=" + stuClass + '}'; } }
創(chuàng)建Stu實體類對象,多一個表中不存在的Class類型的stuClass對象,它表示這個學(xué)生屬于哪個班級,這里是一對一的嵌套查詢因此用association標(biāo)簽
@Mapper public interface StuMapper { Stu getStuById(@Param("stuName") String stuName); }
mapper接口方法是getStuById方法,返回值是Stu學(xué)生對象
<?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="org.apache.mybatisDemo.StuMapper"> <resultMap id="StuMap" type="org.apache.mybatisDemo.Stu"> <id property="id" column="stuId"/> <result property="name" column="stuName"/> <result property="age" column="age"/> <result property="classId" column="class_id"/> <association property="stuClass" javaType="org.apache.mybatisDemo.Class"> <id property="id" column="classId"/> <result property="name" column="className"/> <result property="createTime" column="create_time"/> </association> </resultMap> <select id="getStuById" resultMap="StuMap"> select c.id classId, c.name className, c.create_time, s.id stuId, s.name stuName, s.age, s.class_id from `class` c inner join `stu` s on c.id = s.class_id where s.`name` = #{stuName} </select> </mapper>
mapper.xml文件多表查詢,resultMap的type是org.apache.mybatisDemo.Stu類型,其中stuClass屬性是Class班級類型,是一對一的嵌套查詢因此用association標(biāo)簽,association標(biāo)簽用javaType表示類型是org.apache.mybatisDemo.Class
<mappers> <mapper resource="mybatis/BlogMapper.xml"/> <mapper resource="mybatis/ClassMapper.xml"/> <mapper resource="mybatis/StuMapper.xml"/> </mappers>
mybatis-config.xml文件中注冊StuMapper.xml
@Test public void f8() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession sqlSession = sqlSessionFactory.openSession()) { StuMapper mapper = sqlSession.getMapper(StuMapper.class); Stu stu = mapper.getStuById("張三3"); System.out.println(stu); } }
調(diào)用mapper的getStuById方法
測試結(jié)果是返回一個Stu學(xué)生對象,它包含id=7,name=張三3,age=22,classId=3,stuClass屬性是一個Class班級對象,使用association標(biāo)簽封裝了這個Class班級對象
結(jié)論:一對一的嵌套查詢用association標(biāo)簽
3.2 多表查詢,返回值是List集合,泛型是Stu學(xué)生對象
@Mapper public interface StuMapper { List<Stu> getStuList(); }
返回值是List集合,泛型是Stu學(xué)生對象
<?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="org.apache.mybatisDemo.StuMapper"> <select id="getStuList" resultMap="StuMap"> select c.id classId, c.name className, c.create_time, s.id stuId, s.name stuName, s.age, s.class_id from `class` c inner join `stu` s on c.id = s.class_id </select> </mapper>
mapper.xml的方法中resultMap指定StuMap,還是3.1中的resultMap,只需要指定List集合的泛型即可
@Test public void f9() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession sqlSession = sqlSessionFactory.openSession()) { StuMapper mapper = sqlSession.getMapper(StuMapper.class); List<Stu> stuList = mapper.getStuList(); stuList.forEach(System.out::println); } }
調(diào)用mapper的getStuList方法
測試結(jié)果是查詢得到9個Stu學(xué)生對象,每個學(xué)生對象都封裝了stuClass這個Class班級對象
結(jié)論:一對一的嵌套查詢用association標(biāo)簽,并且mapper接口方法返回值是List集合類型
到此這篇關(guān)于MyBatis使用嵌套查詢collection和association的實現(xiàn)的文章就介紹到這了,更多相關(guān)MyBatis 嵌套查詢collection和association內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- mybatis collection關(guān)聯(lián)查詢多個參數(shù)方式
- mybatis?resultMap之collection聚集兩種實現(xiàn)方式
- mybatis中association和collection的使用與區(qū)別
- MyBatis的collection和association的使用解讀
- Mybatis中一對多(collection)和一對一(association)的組合查詢使用
- Mybatis使用Collection屬性的示例代碼
- Mybatis的collection三層嵌套查詢方式(驗證通過)
- mybatis?collection和association的區(qū)別解析
- MyBatis中<collection>標(biāo)簽的多種用法
相關(guān)文章
java.lang.ExceptionInInitializerError初始化程序中的異常錯誤的解決
java.lang.ExceptionInInitializerError?異常在?Java?中表示一個錯誤,該錯誤發(fā)生在嘗試初始化一個類的靜態(tài)變量、靜態(tài)代碼塊或枚舉常量時,本文就來介紹并解決一下,感興趣的可以了解一下2024-05-05Java后臺Controller實現(xiàn)文件下載操作
這篇文章主要介紹了Java后臺Controller實現(xiàn)文件下載操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10詳解MybatisPlus集成nacos導(dǎo)致druid連接不上數(shù)據(jù)庫
這篇文章主要介紹了詳解MybatisPlus集成nacos導(dǎo)致druid連接不上數(shù)據(jù)庫,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11@RequestMapping 如何使用@PathVariable 從URI中獲取參數(shù)
這篇文章主要介紹了@RequestMapping 如何使用@PathVariable 從URI中獲取參數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08解析SpringBoot @EnableAutoConfiguration的使用
這篇文章主要介紹了解析SpringBoot @EnableAutoConfiguration的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Java格式化輸出詳細(xì)講解(printf、print、println、format等)
Java的格式化輸出等同于String.Format,與C有很大的相似,下面這篇文章主要給大家介紹了關(guān)于Java格式化輸出(printf、print、println、format等)的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03Java線程使用同步鎖交替執(zhí)行打印奇數(shù)偶數(shù)的方法
這篇文章主要介紹了Java線程使用同步鎖交替執(zhí)行打印奇數(shù)偶數(shù)的方法。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01