当前位置: 首页 > news >正文

Mybatis扩展

1 pageHelper

1.1 介绍

  • Mybatis中常用的一个插件,其作用是更加方便的进行分页查询
  • 如果查询的数据量很大,此时我们会选择使用分页查询,减缓服务器压力
SELECT * 
FROM tb_user 
LIMIT index, pageNum;
# index 表示当前页中第一条数据的编号(编号从0开始) 也叫作偏移量
# pageNum 表示一页显示的记录数

1.2 依赖

<!-- pageHelper 插件 -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.3.0</version>
</dependency>

1.3 引入

①UserMapper.xml

<select id="getUserByPage" resultType="User">SELECT id,username,nickname,password,mobile,status,created_time,modified_timeFROM tb_usersLIMIT #{index},#{size};
</select>

②UserDao

/*** 分页查询tb_users表中记录** @param index 每页中的第一条记录的编号(编号从0开始)* @param size  每页显示的记录数* @return*/
public List<User> getUserByPage(Integer index, Integer size);

③TestUser

@Test
public void getUserByPage() {List<User> userList = userDao.getUserByPage(5, 5);for (User user : userList) {System.out.println(user);}
}

1.4 TO类型封装

  • 如果传入的多个参数时,这些参数都不属于业务模型中的数据(不属于POJO中的数据),没有对应的实体类,但是这些数据还是经常被使用的,所以可以也封装为一个类,并用属性描述这些参数,这样的类成为TO类
  • TO(Transfer Object) 数据传输对象
  • 可以封装分页参数

①Page

package cn.tedu.to;public class Page {/*** 每页中的第一条记录的编号(编号从0开始)*/private Integer index;/*** 每页显示的记录数*/private Integer size;public Integer getIndex() {return index;}public void setIndex(Integer index) {this.index = index;}public Integer getSize() {return size;}public void setSize(Integer size) {this.size = size;}
}

②UserMapper.xml

<select id="getUserByPage" resultType="User">SELECT id,username,nickname,password,mobile,status,created_time,modified_timeFROM tb_usersLIMIT #{index},#{size};
</select>

③UserMapper接口

/*** 分页查询tb_users表中记录** @param page 分页数据* @return 指定页的记录*/
public List<User> getUserByPage(Page page);

④TestUser

@Test
public void getUserByPage() {Page page = new Page();page.setIndex(0);page.setSize(5);List<User> userList = userDao.getUserByPage(page);for (User user : userList) {System.out.println(user);}
}

1.5 使用pageHelper

①pom.xml

<!--pageHelper插件-->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.3.0</version>
</dependency>

②PageHelperConfig

  • 如果对插件有其余的设置时,可以设置配置类,否则不添加也可以
@Configuration
public class PageHelperConfig {/*** 当SpringBoot启动时,会自动加载配置类,自动执行配置方法,* 将方法的返回值交给Spring容器管理** @return*/@Beanpublic PageHelper pageHelperInit() {PageHelper pageHelper = new PageHelper();//指定分页时的一些设置Properties p = new Properties();p.setProperty("reasonable", "true"); // 分页合理化return pageHelper;}
}
  • 也可以在配置文件进行设置
pagehelper:reasonable: true

③UserMapper接口

/*** 查询所有用户信息** @return 所有用户信息*/
public List<User> getUser();

④UserMapper.xml

<select id="getUser" resultType="User">SELECT id,username,nickname,password,mobile,status,created_time,modified_timeFROM tb_users
</select>

⑤TestUser

@Test
public void getUser() {//startPage(a,b) 设置分页为第a页,每页有b条记录PageHelper.startPage(5, 5);List<User> userList = userDao.getUser();for (User user : userList) {System.out.println(user);}
}

2 逆向工程

2.1 概念

  • 正向工程: 根据数据库中的表,创建对应的JAVA实体类,然后再创建接口,xml文件等内容
  • 逆向工程: 先创建数据库的表,由框架负责读取数据库表,反向生成如下资源:
    • JAVA实体类
    • Mapper接口
    • Mapper.xml文件

2.2 配置POM

①创建SpringBoot项目,名为MyBatisGeneratorDemo,并将版本改为2.5.4

②在项目的POM中,添加如下依赖

<!--添加MySQL数据库驱动依赖-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>
<!--添加mybatis启动依赖-->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version>
</dependency>

③在项目的POM中的build/plugins组件中,添加如下插件

<!-- 控制Maven在构建过程中的相关配置 -->
<build><!-- 构建过程中要使用的插件 --><plugins><!-- 一个具体的插件 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!-- 逆向工程的操作的相关插件 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.0</version><!-- 插件的依赖 --><dependencies><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency></dependencies></plugin></plugins>
</build>

2.3 配置文件

①在项目的resources目录下,添加一个配置文件,文件名必须是: generatorConfig.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration><!--targetRuntime: 表示进行逆向工程时的版本是什么MyBatis3Simple: 生成最基本的增删改查的SQL语句MyBatis3: 会根据实体表的情况,动态的生成带条件的增删改查的SQL语句--><context id="DB2Tables" targetRuntime="MyBatis3Simple"><!-- 数据库的连接信息 --><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/sblog?characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai"userId="root"password="root"></jdbcConnection><!--JAVA实体类的生成策略targetPackage: 表示实体类存在的包路径是哪里targetProject: 表示实体类所在的包存储到哪个主目录中(基本不会改动)--><javaModelGenerator targetPackage="cn.tedu.pojo" targetProject=".\src\main\java"><property name="enableSubPackages" value="true"/><property name="trimStrings" value="true"/></javaModelGenerator><!--SQL映射文件的生成策略targetPackage: 表示SQL映射文件存在的路径是哪里targetProject: 表示SQL映射文件所在的包存储到哪个主目录中(基本不会改动)--><sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\resources"><property name="enableSubPackages" value="true"/></sqlMapGenerator><!--MAPPER接口的生成策略targetPackage: 表示MAPPER接口存在的路径是哪里targetProject: 表示MAPPER接口所在的包存储到哪个主目录中(基本不会改动)--><javaClientGenerator type="XMLMAPPER" targetPackage="cn.tedu.mapper" targetProject=".\src\main\java"><property name="enableSubPackages" value="true"/></javaClientGenerator><!--逆向分析的表tableName: 表示要读取的数据库中的表名domainObjectName: 表示根据对应的表生成的基础的名字比如: 基础名为Users实体类名: UsersSQL文件名: UsersMapperMAPPER接口: UsersMapper--><table tableName="tb_users" domainObjectName="Users"/></context>
</generatorConfiguration>

②执行插件

  • 如果没有显示,则表示插件引入有问题,检查POM文件是否设置正确

2.4 测试

①将生成的接口上,添加@Mapper注解

@Mapper
public interface UsersMapper {...
}

②然后在项目中添加配置文件application.yml

  • 检查用户密码是否输入有误
  • 检查MAPPER.xml文件的包路径和配置文件的路径是否匹配
  • 检查实体类路径和配置文件设置的路径是否匹配
spring:datasource:url: jdbc:mysql://localhost:3306/sblog?serverTimezone=Asia/Shanghai&characterEncoding=utf8username: rootpassword: rootmybatis:configuration:map-underscore-to-camel-case: truemapper-locations: classpath:/mapper/*.xmltype-aliases-package: cn.tedu.pojologging:level:cn:tedu: debug

③创建测试类,生成测试方法

@SpringBootTest
class TestUser {@Autowiredprivate UsersMapper usersMapper;@Testpublic void selectByPrimaryKey() {Users users = usersMapper.selectByPrimaryKey(1);System.out.println(users);}}

3 延迟加载

3.1 什么是延迟加载

  • 假设要查询指定id为1的文章的信息以及文章所属的用户信息
SELECT a.id,a.title,u.username 
FROM tb_articles a LEFT JOIN tb_users u
ON a.user_id = u.id
WHERE a.id = 1;
  • 假设id为100的文章信息,在数据库中该文章不存在,但是由于SQL已经执行了,导致内存中已经将关联的信息存储起来,所以希望实现如果文章不存在,就不去查询用户表的记录了,以此节省资源
  • 所以使用分部查询的方式来解决这个问题

①首先查询文章表,是否存在记录,如果没查询到记录,则终止查询

SELECT * 
FROM tb_articles 
WHERE id = 1;

②如果查询到了记录,则使用查询的记录中的user_id,作为SQL的id值

SELECT * 
FROM tb_users 
WHERE id = #{id}

3.2 一对一查询

3.2.1 目标

根据文章ID,查询出文章信息,并且查询出文章所属的用户信息,将查询的结果封装到Articles对象中

3.2.2 生成Articles相关逆向工程
  • 使用逆向工程生成tb_articles相关的实体类,SQL映射和接口
  • 并在Articles类中添加用户表的属性
private Users users;public Users getUsers() {return users;
}public void setUsers(Users users) {this.users = users;
}
3.3.3 映射文件
<resultMap id="BaseResultMap" type="cn.tedu.pojo.Articles"><id column="id" property="id" jdbcType="BIGINT"/><result column="title" property="title" jdbcType="VARCHAR"/><result column="TYPE" property="type" jdbcType="CHAR"/><result column="content" property="content" jdbcType="VARCHAR"/><result column="STATUS" property="status" jdbcType="CHAR"/><result column="user_id" property="userId" jdbcType="BIGINT"/><result column="created_time" property="createdTime" jdbcType="TIMESTAMP"/><result column="modified_time" property="modifiedTime" jdbcType="TIMESTAMP"/><!--①通过select属性,调用第二步要执行的SQL--><!--②通过column属性,来制定第二步要传入的参数是那个属性值--><!--③通过property属性,封装第二条SQL传入的结果--><!--④通过fetchType属性,表示本次的延迟加载是懒加载模式--><association property="users"javaType="Users"select="cn.tedu.mapper.UsersMapper.selectByPrimaryKey"column="user_id"fetchType="lazy"></association>
</resultMap>
3.3.4 测试类

①查询文章信息,不获取用户信息,执行查询文章表的SQL

@Test
public void selectArticleByPrimaryKey() {Articles articles = articlesMapper.selectByPrimaryKey(1L);System.out.println(articles.getTitle());
}

②获取用户信息,会自动查询用户表的SQL

@Test
public void selectArticleByPrimaryKey() {Articles articles = articlesMapper.selectByPrimaryKey(1L);System.out.println(articles.getUsers());
}

3.3 一对多查询

3.2.1 目标

根据用户ID查询用户信息,并且查询出该用户的所有的文章信息,将查询的结果封装到User对象中

3.2.2 添加Articles属性
  • Users类中,添加属性封装关联的文章信息
private List<Articles> articles;public List<Articles> getArticles() {return articles;
}public void setArticles(List<Articles> articles) {this.articles = articles;
}
3.3.3 映射文件

①在ArticlesMapper.xml中定义根据user_id查询文章信息的SQL

<select id="selectByUserId" resultMap="BaseResultMap">SELECT id, title, TYPE, content, STATUS, user_id, created_time, modified_timeFROM tb_articlesWHERE user_id = #{userId}
</select>

②在ArticlesMapper接口中定义接口

List<Articles> selectByUserId(Long userId);

③在User类中,定义一对多的延迟加载的映射

同学们!!!这个案例映射失败的原因是因为我在collection标签中,写错了属性,不能写javaType属性,要写出ofType属性才可以!!!不要像我一样马虎哦!!!!

<resultMap id="BaseResultMap" type="cn.tedu.pojo.Users"><!--WARNING - @mbggeneratedThis element is automatically generated by MyBatis Generator, do not modify.This element was generated on Fri Jun 09 20:34:40 CST 2023.--><id column="id" property="id" jdbcType="INTEGER"/><result column="username" property="username" jdbcType="VARCHAR"/><result column="nickname" property="nickname" jdbcType="VARCHAR"/><result column="password" property="password" jdbcType="VARCHAR"/><result column="mobile" property="mobile" jdbcType="VARCHAR"/><result column="status" property="status" jdbcType="TINYINT"/><result column="created_time" property="createdTime" jdbcType="TIMESTAMP"/><result column="modified_time" property="modifiedTime" jdbcType="TIMESTAMP"/><collection property="articles"ofType="Articles"select="cn.tedu.pojo.Articles.selectByUserId"column="id"fetchType="lazy"></collection>
</resultMap>
3.3.4 测试类

①查询用户信息,不获取文章信息,执行查询用户表的SQL

@Test
public void selectByPrimaryKey() {Users users = usersMapper.selectByPrimaryKey(1);System.out.println(users.getUserName());
}

②获取文章信息,会自动查询文章表的SQL

@Test
public void selectByPrimaryKey() {Users users = usersMapper.selectByPrimaryKey(1);System.out.println(users.getArticles());
}

4 Maven中的scope

maven坐标中的scope表示依赖的作用范围

通常有以下几个作用范围:

  • compile: 这是默认的作用范围,表示依赖会被编译到项目中,并且会在运行时对项目产生影响
  • provided: 表示依赖会在编译时使用,但是在运行时需要额外的提供
  • runtime: 表示依赖不会被编译到项目中,但是运行时会使用到
  • test: 表示此以来使用在测试中

5 Maven的version

maven坐标中的version表示的是依赖的版本号

通常有以下的值:

  • SNAPSHOT: 表示此版本是开发中的版本,可能会存在频繁的更新和变动
  • RELEASE: 表示稳定的、成熟的版本,不会经常的变动版本号
  • GA: 表示正式版本,以正式发布,不会经过重大更大

上一篇文章:Java综合项目(day38)-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/Z0412_J0103/article/details/142972779下一篇文章: 

 


http://www.mrgr.cn/news/55168.html

相关文章:

  • 如何利用 Python抓取网页数据 其他方式抓取网页数据列举
  • 重置时把el-tree树节点选中状态取消
  • Java 当中使用 “google.zxing ”开源项目 和 “github 的 qrcode-plugin” 开源项目 生成二维码
  • Linux下进程通信原理图(详细)总结附实例代码快速掌握
  • 软件设计模式------概述
  • 数据结构与集合源码
  • Dockerfile 中,把多个 RUN 合并在一起,能减少镜像尺寸吗?
  • 特斯拉自动驾驶出租车计划变成泡影?联想与Meta合作,推出面向PC的个人AI智能体AI Now|AI日报
  • 学生学籍管理系统设计与实现(源码+定制+开发)
  • Varchar(255)可以存255个汉字
  • 为什么互动投影墙在儿童展馆中如此受欢迎?创新互动是关键吗?
  • 【AIGC】ChatGPT提示词Prompt高效编写模式:Self-ask Prompt、ReACT与Reflexion
  • 加速应用开发:低代码平台云SaaS和源码交付模式如何选
  • 大路灯有必要买吗?五款口碑最好的护眼大路灯推荐
  • Spring security 自定义 token 身份验证
  • 学习docker第五弹------Docker容器数据卷
  • 【题解】—— LeetCode一周小结42
  • 一般HR面试程序员会问什么问题?
  • 如何在分布式环境中实现高可靠性分布式锁
  • Openlayers高级交互(4/20):手绘多边形,导出KML文件,可以自定义name和style
  • 分布式系统中的Dapper与Twitter Zipkin:链路追踪技术的实现与应用
  • 全面击破工程级复杂缓存难题
  • 温度传感器
  • Java网络编程 - headers
  • YOLOv11模型改进-注意力-引入简单无参数注意力模块SimAM 提升小目标和遮挡检测
  • 华为OD机试 - 贪心歌手 - 动态规划(Python/JS/C/C++ 2024 D卷 200分)