java学习之 MyBatis-day02

Mapper组件

  1. 使用Mapper组件
  • 类似DAO,在接口中定义 CRUD 等操作方法。Mapper 组件 = Mapper 接口 + Mapper XML 文件。
  • 接口的命名为实体名 + Mapper,一般和其对应 XML 文件放一起
  • XML 命名空间及 namespace="用其对应接口的全限定名"
  • Mapper 接口的方法名要和 Mapper XML 文件元素 一致
  • 方法的返回类型对应 SQL 元素中定义的 resultType / resultMap 类型;
  • 方法的参数类型对应 SQL 元素中定义的 paramterType 类型(一般不写)。
Mapper 接口的原理

接口是规范,实质做的实现还是要由实现类对象来做,而这个实现类不需要我们写,实现类对象也不由我们创建,这些都 MyBatis 使用动态代理帮我们做了 提供 Mapper 接口对应 Mapper XML 文件,获取实现类对象的时候传入 Mapper 接口字节码

@Param 注解

@Param 注解是 MyBatis 中的一个注解,用于指定方法参数的名称。它的主要作用是解决方法参数名称在编译期被丢失的问题,并且可以让你在 XML 映射文件中更加清晰地引用方法参数。

指定方法参数的名称: Java 中,方法参数的名称在编译后会被丢弃,而只保留参数的类型。这意味着在 XML 映射文件中,你无法通过参数名称来引用方法参数。使用 @Param 注解可以为方法参数指定一个名称,这个名称将用于 XML 映射文件中

java
复制代码
public List<User> findUsers(@Param("name") String name, @Param("age") int age);

当传递一个 List 对象或数组对象参数给 MyBatis 时,MyBatis 会自动把它包装到一个 Map 中,此时:List 对象会以 list 作为 key,数组对象会以 array 作为 key,也可以使用注解 @Param 设置 key 名。

MyBatis 的 # 和 $

特性# 占位符$ 占位符
参数替换方式安全替换(预编译)文本替换(不安全)
替换参数使用?替代参数直接替换参数值
替换后的值将参数值作为预编译参数将参数值直接嵌入 SQL 文本
防止 SQL 注入攻击
支持表名和列名替换
字符串拼接不需要手动添加单引号需要手动添加单引号
适用于参数的数据类型通常适用于所有数据类型主要用于处理字符串和 SQL 片段
推荐使用推荐使用 #慎用 $,容易受到 SQL 注入攻击的风险
示例WHERE id = #{id}WHERE id = ${id}

动态SQL

利用动态 SQL 这一特性可以彻底摆脱根据不同条件拼接 SQL 语句的痛苦

  • <where> 标签

<where> 标签用于在 SQL 查询中包装多个条件,通常是多个条件之间使用 AND 连接。这个标签会自动处理前置的 WHERE 关键字,并且只在有条件存在时添加 WHERE 关键字。

-if 标签

<if> 标签用于根据条件包含或排除 SQL 查询的一部分。它允许你在运行时检查一个条件,如果条件为真,则包含<if>标签内的内容,否则将忽略它。

例如:

xml
复制代码
<select id="selectUsers" parameterType="User" resultType="User"> SELECT * FROM users <where> <if test="name != null"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> </where> </select>

示例中,< where > 标签包装了两个 < if > 标签,每个 < if > 标签用于检查一个条件是否满足。如果 name 和/或 age 存在,则它们会被包含在 WHERE 子句中,否则 WHERE 子句将为空。

多表查询

关系应用

生活中数据很多是存在关系,且存储的数据也能表示出来这种关系

  • 保存:页面的数据 ---> 使用 Java 对象封装 ---> 通过 MyBatis ---> 数据库表的数据
  • 查询:数据库表的数据 ---> 通过 MyBatis ---> 封装成 Java 对象 ---> 页面展示数据

对象关系分类

  • 泛化关系
  • 实现关系
  • 依赖关系
  • 关联关系
  • 聚合关系
  • 组合关系

关联关系

A 对象依赖 B 对象,并且把 B 作为 A 的一个成员变量,则 A 和 B 存在关联关系。在 UML 中依赖通常使用实线箭头表示。

分类
  1. 按照导航性分

若通过 A 对象中的某一个属性可以访问到 B 对象,则说 A 可以导航到 B。

  • 单向:只能从 A 通过属性导航到 B,B 不能导航到 A。
  • 双向:A 可以通过属性导航到 B,B 也可以通过属性导航到 A。
  1. 按照多重性分
  • 一对一
  • 一对多
  • 多对一
  • 多对多。
判断关联关系的分类
  • 判断都是从对象的实例上面来看的;
  • 判断关系需要根据对象的属性;
  • 判断关系必须确定具体需求

单向多对一之额外 SQL 查询

单向多对一关系通常用于描述一个实体(多的一端)关联到另一个实体(一的一端)。在MyBatis中,您可以使用额外的SQL查询来检索与多对一关系相关联的数据。

以下是单向多对一关系中使用额外SQL查询的示例:

假设我们有两个实体类:Student 和 Cource ,假设一个学生对应一个课程,即多个学生可能有同一课程。

实体类示例:

java
复制代码
//课程类 @AllArgsConstructor @Getter @Setter @ToString @NoArgsConstructor public class Course { private Long id; private String Name; } //学生类 @Getter @Setter @AllArgsConstructor @NoArgsConstructor @ToString public class Student { private Long id; private String Name; private Integer Age; private Course course; }

映射文件示例:

xml
复制代码
<!--课程查询 --> <resultMap id="CourseResultMap" type="Course"> <id property="id" column="ID"/> <result property="Name" column="CouName"/> </resultMap> <select id="selectById" resultMap="CourseResultMap"> select * from course where id=#{id} </select> <!--学生查询 --> <!-- 通过查询过程中的id查询 对应的课程信息 --> <resultMap id="BaseMap" type="Student"> <id property="id" column="id"/> <result property="name" column="StuName"/> <result property="age" column="StuAge"/> <association property="course" select="mybatis.xyz.bycor.mapper.CourseMapper.selectById" column="Cid"> </association> </resultMap> <!-- 查询单个学生的信息 (包括课程信息) --> <select id="selectById" resultMap="BaseMap"> SELECT * FROM student where id=#{id} </select> <!-- 查询所有学生的信息 (包括课程信息) --> <select id="selectAll" resultMap="BaseMap"> SELECT * FROM student </select> <!-- 查询所有学生的信息 (包括课程信息) 方式 2--> <resultMap id="BaseMap2" type="Student" > <id column="id" property="id"/> <result column="StuName" property="name"/> <result column="StuAge" property="age"/> <result column="CouName" property="course.name"/> <result column="Cid" property="course.id"/> </resultMap> <select id="selectAll2" resultMap="BaseMap2"> select s.id,s.StuName,s.StuAge,c.CouName,c.id Cid from student s join course c on c.id = s.Cid </select> <!-- 查询所有学生的信息 (包括课程信息) 方式 3--> <resultMap id="BaseMap3" type="Student"> <id column="id" property="id"/> <result column="StuName" property="name"/> <result column="StuAge" property="age"/> <association property="course" columnPrefix="c_" javaType="Course"> <result column="id" property="id"/> <result column="CouName" property="name"/> </association> </resultMap> <select id="selectAll3" resultMap="BaseMap3"> select s.id,s.StuName,s.StuAge,c.CouName c_CouName,c.id c_id from student s join course c on c.id = s.Cid </select>

Java Mapper代码示例:

java
复制代码
public interface CourseMapper { // 增删 改 查 void delete(Long id); void update(Course course); List<Course> selectAll(); void insert(Course course); Course selectById(Long id); } public interface StudentMapper { // 增删 改 查 void insert(Student student); void delete(Long id); void update(Student student); Student selectById(Long id); List<Student> selectAll(); List<Student> selectAll2(); List<Student> selectAll3(); }

Java Test代码示例:

java
复制代码
@Test public void testMany2OneSelect() { // 查询某个的学生信息包括对应的课程信息 SqlSession sqlSession = MybatisUtil.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.selectById(2L); sqlSession.close(); System.out.println(student); } @Test public void testMany2OneSelectAll() { // 查询所有学生信息包括对应的课程信息 SqlSession sqlSession = MybatisUtil.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.selectAll(); sqlSession.close(); students.forEach(System.out::println); }

在上述示例中,我们定义了一个名为 selectAllXXX 的查询操作,它用于获取所有学生的信息,包括他们所选的课程信息。这个查询使用了一个自定义的结果映射 BaseMap3,将学生的属性和相关的课程信息进行关联。

下面是这个查询的要点总结:

查询操作:selectAll3,用于获取所有学生的信息以及他们所选的课程信息。

结果映射:BaseMap3,自定义结果映射,用于将查询结果映射到 Student 类型的对象上。

查询语句:SQL 查询语句联接了 student 表和 course 表,通过学生表的外键关联了相关的课程信息。

结果映射配置:在结果映射中,我们定义了学生属性的映射,以及关联的课程属性的映射。这样,查询结果将自动映射到 Student 对象的属性中,包括学生的基本信息和所选课程的信息。

通过这种方式,我们可以一次性获取学生和他们所选课程的信息,无需手动处理查询结果集的关联,提高了代码的可读性和查询效率。这是 MyBatis 中处理多表关联查询的一种常见方法。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP