MyBatis 关联查询

目录

一、一对一查询(sqlMapper配置文件)

1、需求:

2、创建account和user实体类

3、创建AccountMapper 接口

4、创建并配置AccountMapper.xml

5、测试

二、一对多查询(sqlMapper配置文件)

1、需求:

2、创建user和account实体类

3、创建UserMapper 接口

4、创建并配置UserMapper.xml

5、测试

三、多对多查询(sqlMapper配置文件)

1、需求:

2、创建role、user实体类

3、创建RoleMapper 接口

4、创建并配置RoleMapper.xml

5、测试

四、MyBAtis注解

1、基本常用的注解有:

2、复杂关系的注解(一对一、一对多/多对一、多对多关系)

五、一对一查询(注解)

六、一对多查询(注解)

一对多反过来测试

六、多对多关系注解方式的查询数据


关联查询

当访问关系的一方时,如果需要查看与之关联的另一方数据,则必须使用表链接查询,将查询到的另一方数据,保存在本方的属性中

实体间的关系(拥有 has、属于 belong)

  • OneToOne:一对一关系(account ←→ user)

  • OneToMany:一对多关系(user ←→ account)

  • ManyToMany:多对多关系(user ←→ role)

关联查询的语法

  • 指定“一方”关系时(对象),使用< association javaType="" >
  • 指定“多方”关系时(集合),使用< collection ofType="" >

一、一对一查询(sqlMapper配置文件)

1、需求:

查询账户(account)信息,关联查询用户(user)信息。

分析:因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。

2、创建accountuser实体类

Account.java

public class Account implements Serializable {private Integer id;private Integer uid;private Double money;// 另外一方private User user;//get set toString方法此处省略
}

User.java

public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;//get set toString方法此处省略
}
3、创建AccountMapper 接口
public interface AccountMapper {Account getAccountById(Integer id);
}
4、创建并配置AccountMapper.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.by.mapper.AccountMapper"><resultMap id="getAccountByIdResult" type="com.by.pojo.Account"><id column="aid" property="id"></id><result column="uid" property="uid"></result><result column="money" property="money"></result><!--一对一使用association标签指定数据的封装规则property="user":Account的属性名javaType="com.by.pojo.User":等价于resultType--><association property="user" javaType="com.by.pojo.User"><id column="id" property="id"/><result column="username" property="username"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><result column="address" property="address"/></association></resultMap><select id="getAccountById" parameterType="int" resultMap="getAccountByIdResult">SELECT a.id aid, a.uid uid, a.money money, u.* FROM account a LEFT JOIN user u ON a.uid=u.id WHERE a.id=#{id}</select>
</mapper>
5、测试
 /*** 一对一:一个Account 对 一个User*/@Testpublic void testGetAccountById(){//加载mybatis-config.xmlString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);//创建sqlSessionFactorySqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//创建sqlSessionSqlSession sqlSession = sessionFactory.openSession();AccountMapper accountMapper = sqlSession.getMapper(AccountMapper.class);Account account = accountMapper.getAccountById(1);System.out.println(account);//释放资源sqlSession.close();inputStream.close();}

二、一对多查询(sqlMapper配置文件)

1、需求:

查询所有用户(user)信息及用户关联的账户(account)信息。

分析:用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,此时左外连接查询比较合适。

2、创建useraccount实体类

User.java

public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;//对应多方,需要用集合private List<Account> accountList;//get set toString方法此处省略
}

Account.java

public class Account implements Serializable {private Integer id;private Integer uid;private Double money;// 另外一方private User user;//get set toString方法此处省略
}
3、创建UserMapper 接口
public interface UserMapper {User getUserById(Integer id);
}
4、创建并配置UserMapper.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.by.mapper.UserMapper"><resultMap id="getUserByIdResult" type="com.by.pojo.User"><id column="id" property="id"></id><result column="username" property="username"/><result column="address" property="address"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><!--一堆多使用collection标签指定数据的封装规则--><collection property="accountList" ofType="com.by.pojo.Account"><id column="aid" property="id"></id><result column="uid" property="uid"></result><result column="money" property="money"></result></collection></resultMap><select id="getUserById" parameterType="int" resultMap="getUserByIdResult">SELECT u.*, a.id aid, a.uid uid, a.money money FROM user u LEFT JOIN account a ON u.id=a.uid WHERE u.id=#{id}</select>
</mapper>
5、测试
    /*** 一对多:一个user 对 多个Account*/@Testpublic void testGetUserById(){//加载mybatis-config.xmlString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);//创建sqlSessionFactorySqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//创建sqlSessionSqlSession sqlSession = sessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user = userMapper.getUserById(41);System.out.println(user);//释放资源sqlSession.close();inputStream.close();}

三、多对多查询(sqlMapper配置文件)

1、需求:

查询角色及角色赋予的用户信息。

分析:一个用户可以拥有多个角色,一个角色也可以赋予多个用户,用户和角色为双向的一对多关系,多对多关系其实我们看成是双向的一对多关系。

2、创建role、user实体类

Role.java
public class Role {private Integer id;private String roleName;private String roleDesc;//对应多方,需要用集合private List<User> userList;//get set toString方法此处省略}

User.java

public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;//get set toString方法此处省略
}
3、创建RoleMapper 接口
public interface RoleMapper {Role getRoleById(Integer id);
}
4、创建并配置RoleMapper.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.by.mapper.RoleMapper"><resultMap id="getRoleByIdResultMap" type="com.by.pojo.Role"><id column="rid" property="id"></id><result column="role_name" property="roleName"></result><result column="role_desc" property="roleDesc"></result><!--一对多使用collection标签指定数据的封装规则property="userList":pojo的属性ofType="com.by.pojo.User":集合的泛型,等价于resultType--><collection property="userList" ofType="com.by.pojo.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="getRoleById" parameterType="int" resultMap="getRoleByIdResultMap">SELECTr.id as rid,r.role_name,r.role_desc,u.*FROMuser_role urJOIN role r ON ur.rid=r.idJOIN user u ON ur.uid=u.idWHEREr.id=#{id}</select>
</mapper>
5、测试
  /*** 多对多:一个user 对 多个role   一个role 对 多个user*/@Testpublic void testGetUserById(){//加载mybatis-config.xmlString resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);//创建sqlSessionFactorySqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//创建sqlSessionSqlSession sqlSession = sessionFactory.openSession();@Testpublic void testGetRoleById(){RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);Role role = roleMapper.getRoleById(1);System.out.println(role);}//释放资源sqlSession.close();inputStream.close();}

四、MyBAtis注解

1、基本常用的注解有:

@Insert: 实现新增

@Update:实现更新

@Select:实现查询

@Result:实现结果集封装

@Results:可以与@Result一起使用,封装多个结果的集合(其内使用@Result处理当前对象的基本属性,再处理返回值)

@ResultMap:实现引用@Results定义的封装

@One:实现一对一结果集 封装

@Many:实现一对多结果集封装

@SelectProvider:实现动态SQL映射

@CacheNamespace:实现注解二级缓存的使用

注意:复杂的注解不好编写的情况下可以使用Mapper文件配合使用

2、复杂关系的注解(一对一、一对多/多对一、多对多关系)

相关注解介绍 :
@Results注解:
@Results代替了标签< resultMap> 该注解中可以使用单个@Result注解,也可以使用@Result集合

格式:

@Results ({@Result () , @Result ()}) 或者@Result (@Result())

@Result 注解:
@Result注解代替了< id> 标签和< result>标签

@Result 中 的 属性介绍:
id 是否是主键字段

column 数据库中列的名

property 需要装配的属性名

one 需要使用 @One 注解 (@Result (one = @One) ())

many 需要使用的@Many 注解 (@Result (many = @many) ())

@One 注解(一对一):
代替了< association>标签,是多表查询的关键,在注解中用来制定子查询返回单一对象

@One 注解属性介绍:
select 指定用来多表查询 的 sqlmapper

fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。

语法格式:

@Result(column = " “,property=” ",one=@Onet(select = " "))

@Many 注解(多对一)
代替了< Collection>标签,是多表查询的关键,在注解中用来指定子查询返回对象集合。

注意:聚集元素用来处理"一对多"的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList)但是注解中可以不定义;

语法格式:

@Result(property=" “,column=” “,many=@Many(select=” "))

五、一对一查询(注解)

在HusbandMapper.java接口中使用注解进行查询注入数据

HusbandMapper.java

package com.etime.mapper;import com.etime.pojo.Husband;
import com.etime.pojo.Wife;
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 HusbandMapper {//使用一对一关系注解实现查询@Select("select * from husband")//查询所有丈夫的信息//将信息放入结果集合中@Results({@Result(property = "hid",column = "hid"),//设置字段属性对应的数据库列名@Result(property = "hname",column = "hname"),@Result(property = "wid",column = "wid"),//对根据丈夫表内的对应妻子wid到妻子表中查找妻子的信息@Result(property = "wife",javaType = Wife.class,column = "wid",one=@One(select = "com.etime.mapper.WifeMapper.getWifeByWid"))})List<Husband> getAllHusband();
}

在WifeMapper.java中进行注解的使用,对妻子的基本数据进行数据查取

package com.etime.mapper;import com.etime.pojo.Wife;
import org.apache.ibatis.annotations.Select;public interface WifeMapper {//通过@Select查询注解的方方式获取到妻子的基本数据@Select("select * from wife where wid=#{wid}")Wife getWifeByWid(int wid);
}

对妻子和丈夫的一对一的关系进行测试

//使用一对一关系注解查询丈夫和妻子的基本信息@Testpublic void t07(){SqlSession sqlSession =sqlSessionUtil.getSqlSession();HusbandMapper husbandMapper = sqlSession.getMapper(HusbandMapper.class);List<Husband> list = husbandMapper.getAllHusband();list.forEach(System.out::println);sqlSession.close();}

六、一对多查询(注解)

这里即将的测试的关系是多个学生属于同一班的关系

创建学生实体类

package com.etime.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {private int sid;private String sname;private int cid;//创建一个班级类的属性给到学生实体类,不同的学生来自不同的班,多个学生属于同一个班级private Classes classes;
}

创建班级实体类

package com.etime.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@NoArgsConstructor
@AllArgsConstructor
@Data
public class Classes {private int cid;private String cname;
}

在StudentMapper.java接口中使用注解的方式处理查询语句一查查询到的数据 问题,并处理 查询到的班级classes返回的值

package com.etime.mapper;import com.etime.pojo.Classes;
import com.etime.pojo.Student;
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 StudentMapper {//使用@Select查询所有学生信息@Select("select * from student")//使用@Results注解处理查询到的学生实体类中的基本属性以及对应的班级信息//并通过one = @One 的方式把查询到接收到的返回班级实体类进行处理@Results({@Result(property = "sid",column = "sid"),@Result(property = "sname",column = "sname"),@Result(property = "cid",column = "cid"),@Result(property = "classes",javaType = Classes.class,column = "cid",one = @One(select = "com.etime.mapper.ClassesMapper.getClassesByCid"))})List<Student> getAllStudent();
}

在ClassesMapper.java中使用注解的方式根据班级id查询班级的相关信息

ClassesMapper.java

package com.etime.mapper;import com.etime.pojo.Classes;
import org.apache.ibatis.annotations.Select;public interface ClassesMapper {//使用@Select注解的方式通过查询返回值为班级对象给到学生实体类做数据处理的StudentMapper接口的one = @One处理@Select("select * from classes where cid=#{cid}")Classes getClassesByCid(int cid);
}

编写测试

@Testpublic void t08(){SqlSession sqlSession = sqlSessionUtil.getSqlSession();StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);List<Student> list = studentMapper.getAllStudent();list.forEach(System.out::println);sqlSession.close();}

由上面的准备我们将测试多对一查询的情况

一对多反过来测试

对代码进行修改测试查看是否书写更简便些

修改学生实体类

Student.java

package com.etime.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {private int sid;private String sname;private int cid;
}

对班级实体类进行修改

Classes.java

package com.etime.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;@NoArgsConstructor
@AllArgsConstructor
@Data
public class Classes {private int cid;private String cname;List<Student> stuList;
}

对学生类的数据获取接口做修改

public interface StudentMapper {//使用@Select查询所有学生信息@Select("select * from student where cid=#{cid}")Student getStudentByCid(int cid);
}

对班级类进行数据获取进行数据处理

package com.etime.mapper;import com.etime.pojo.Classes;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;import java.util.List;public interface ClassesMapper {//使用@Select注解的方式通过查询返回值为学生对象给到班级实体类做数据处理的ClassesMapper接口的many = @Many多条数据处理//其实由这里可以看出来多对一和一对多是差不多的看是哪一个为主体//这里返回来处理的是集合所以javaType给到的是List.call 数据做处理的也是@Many注解(注意many=@Many别误解为多对多)@Select("select * from classes")@Results({@Result(property = "cid",column = "cid"),@Result(property = "cname",column = "cname"),@Result(property = "stuList",javaType = List.class,column = "cid",many = @Many(select = "com.etime.mapper.StudentMapper.getStudentByCid"))})List<Classes> getAllClasses();
}

由上可知的一对多的方式进行的数据查询可以看出,其实两种方式都差不多,只是看是怎么看他们之间的关系型,以谁为主体

六、多对多关系注解方式的查询数据

众所周知的学生和课程之间是常见的多对多的关系,接下来就以学生关系来测试多对多的关系

创建课程实体类

package com.etime.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@AllArgsConstructor
@Data
@NoArgsConstructor
public class Course {private int courseid;private String coursename;
}

创建学生实体类对象

Student.java

package com.etime.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.util.List;@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student implements Serializable {private int sid;private String sname;private int cid;private List<StudentCourse> studentCourseList;
}

创建学生和课程的关系表的实体类

StudentCourse.java

package com.etime.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@NoArgsConstructor
@AllArgsConstructor
@Data
public class StudentCourse {private int scid;private int sid;private int courseid;private Course course;
}

创建课程CourseMapper.java接口查询数据

package com.etime.mapper;import com.etime.pojo.Course;
import org.apache.ibatis.annotations.Select;public interface CourseMapper {//由课程id到课程表中进行查询课程信息@Select("select * from course where courseid=#{courseid}")Course getCourseByCourseid(int courseid);
}

创建学生StudentMapper.java接口查询数据处理

package com.etime.mapper;import com.etime.pojo.Classes;
import com.etime.pojo.Student;
import org.apache.ibatis.annotations.*;import java.util.List;public interface StudentMapper {//使用@Select查询所有学生信息//通过@Result注解中的属性many = @Many进行数据处理,将得到的课程对象返回到学生实体类对象studentCourseList中@Select("select * from student")@Results({@Result(property = "sid",column = "sid"),@Result(property = "sname",column = "sname"),@Result(property = "cid",column = "cid"),@Result(property = "studentCourseList",javaType = List.class,column = "sid",many = @Many(select = "com.etime.mapper.StudentCourseMapper.getStudentCourseBySid"))})List<Student> getStudentAndCourse();
}

创建学生课程接口StudentCourseMapper.java查询数据,对数据进行处理

package com.etime.mapper;import com.etime.pojo.Course;
import com.etime.pojo.StudentCourse;
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 StudentCourseMapper {//@Select同样的通过注解的方式对数据进行全部查询,处理的通过id查询到的课程单个实体类@Select("select * from studentcourse where sid=#{sid}")@Results({@Result(property = "scid",column = "scid"),@Result(property = "sid",column = "sid"),@Result(property = "courseid",column = "courseid"),@Result(property = "course",javaType = Course.class,column = "courseid",one = @One(select = "com.etime.mapper.CourseMapper.getCourseByCourseid"))})//根据学生id查找所有课程对应的idList<StudentCourse> getStudentCourseBySid(int sid);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/294010.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flask之文件管理网页(上传,下载,搜索,登录,注册) -- 翔山 第一版

前面说要做一个可以注册&#xff0c;登录&#xff0c;搜索&#xff0c;上传下载的网页&#xff0c;初版来了 第一版主代码 from flask import request, Flask, render_template, redirect, url_for, send_from_directory import bcrypt import ossavePath os.path.join(os.ge…

Apache Flink 进阶教程(七):网络流控及反压剖析

目录 前言 网络流控的概念与背景 为什么需要网络流控 网络流控的实现&#xff1a;静态限速 网络流控的实现&#xff1a;动态反馈/自动反压 案例一&#xff1a;Storm 反压实现 案例二&#xff1a;Spark Streaming 反压实现 疑问&#xff1a;为什么 Flink&#xff08;bef…

SVM —— 代码实现

SMO 算法的实现步骤&#xff1a; 代码如下&#xff1a; import numpy as np import matplotlib.pyplot as plt import seaborn as sns import random# 设置中文字体为宋体&#xff0c;英文字体为 times new roman sns.set(font"SimSun", style"ticks", fo…

【虹科分享】金融服务急需数据层改造

文章速览&#xff1a; 数字化转型正在颠覆银行与金融业金融服务的未来Redis Enterprise赋能实时金融应用 金融服务越来越注重实时互动体验&#xff0c;重构关键业务流程&#xff0c;从数据层入手该怎么做&#xff1f; 一、数字化转型正在颠覆银行与金融业 金融科技行业的初创…

7. 结构型模式 - 代理模式

亦称&#xff1a; Proxy 意图 代理模式是一种结构型设计模式&#xff0c; 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问&#xff0c; 并允许在将请求提交给对象前后进行一些处理。 问题 为什么要控制对于某个对象的访问呢&#xff1f; 举个例子&#xff…

Android Studio各种Gradle常见报错问题及解决方案

大家好&#xff0c;我是咕噜铁蛋&#xff01;在开发Android应用程序时&#xff0c;我们可能会遇到各种Gradle错误。这些错误可能来自不同的原因&#xff0c;例如依赖项问题、配置错误、版本冲突等。今天我通过搜索整理了一下&#xff0c;在这篇文章中&#xff0c;我将分享一些常…

Python深度学习029:pytorch中常用的模块或方法

PyTorch是一个广泛使用的深度学习库,提供了许多用于构建和训练神经网络的模块和方法。下面是一些PyTorch中常用的模块和方法的简要介绍: PyTorch常用模块和方法 torch 用途:PyTorch的基础模块,提供了多种数学运算功能。常用方法: torch.tensor():创建张量torch.randn():…

微软官方镜像下载大全(windows iso 官方镜像)

原本只是想下一个Windows Server 2022中文版的镜像&#xff0c;后面发现要么就是慢得一批的某盘&#xff0c;要么就是磁力&#xff0c;我想直接下载简简单单&#xff0c;找了一圈没有找到。官网下载需要注册、登录乱七八糟&#xff0c;最终终于找到下载方法了&#xff0c;适用于…

人工智能_机器学习070_SVM支持向量机_软间隔及优化_硬间隔_衡量间隔软度_引入松弛变量_理解隔离参数---人工智能工作笔记0110

我们继续说,之前说的C是什么意思? 我们在这个软间隔优化中就可以引出C 可以看到之前我们讨论的问题,都是基于样本点的,完全的线性可分的问题,我们称为硬间隔 可以看到这种,一分就可以,分开,简单分割就可以分开的数据,我们称之为硬间隔 但是可以看到上面这种情况,无论怎么分,都…

分布式搜索elasticsearch概念

什么是elasticsearch&#xff1f; elasticsearch是一款非常强大的开源搜索引擎&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 目录 elasticsearch的场景 elasticsearch的发展 Lucene篇 Elasticsearch篇 elasticsearch的安装 elasticsearch的场景 elasticsear…

层次分析法

层次分析法主要用于解决评价类问题(例如选择哪种方案最好&#xff0c;哪位运动员或者员工表现的更优秀) 先用一道引出层次分析法的例题&#xff1a;小明同学高考填完志愿后&#xff0c;小明想出去旅游。在查阅了网上的攻略后&#xff0c;他初步选择了苏杭、北戴河和桂林三地之一…

Docker——微服务的部署

Docker——微服务的部署 文章目录 Docker——微服务的部署初识DockerDocker与虚拟机Docker架构安装DockerCentOS安装Docker卸载&#xff08;可选&#xff09;安装docker启动docker配置镜像加速 Docker的基本操作Docker的基本操作——镜像Docker基本操作——容器Docker基本操作—…