MySQL 数据库 下 使用 MyBatis 进行主子表数据查询骚操作

MySQL 数据库 下 使用 MyBatis 进行主子表数据查询骚操作

在实际开发过程中经常会碰到 主表、从表 这样的数据库设计,本文将介绍一下 主、从表 查询、删除 的 Sao 操作。其中涉及到了 MyBatis resultMap 标签 继承复用嵌套 的应用;废话不多少,喜欢的深入研究下,详情参考如下代码:


<?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.imis.server.mapper.DemoMapper">

	<!--
		MyBatis resultMap 标签继承、复用、嵌套

			继承: 继承已存在的 resultMap 标签进行扩展
			复用: 跨mapper文件引用现存的 resultMap 标签
			嵌套: 多层嵌套的JavaBean与 resultMap 映射方法

	-->

	<!--
	 	@Data // lombok 插件
		@EqualsAndHashCode(callSuper = true)
		@Accessors(chain = true)
		public class MasterTable implements Serializable {

			private static final long serialVersionUID = 1L;

			/**
			 * ID
			 */
			@TableField("id")
			private Integer departmentType;

			/**
			 * 名称
			 */
			@TableField("name")
			private String departmentName;

		}

	 -->

	<resultMap id="Master_BaseResultMap" type="com.imis.server.entity.MasterTable">
		<id column="id" property="id" jdbcType="VARCHAR" />
		<result column="name" property="name" jdbcType="VARCHAR" />
	</resultMap>

	<!--
	 	@Data // lombok 插件
		@EqualsAndHashCode(callSuper = true)
		@Accessors(chain = true)
		public class ChildTable implements Serializable {

			private static final long serialVersionUID = 1L;

			/**
			 * ID
			 */
			private Integer departmentType;

			/**
			 * 父级 ID
			 */
			private String parentId;

			/**
			 * 名称
			 */
			private String departmentName;

		}

	 -->

	<resultMap id="Child_BaseResultMap" type="com.imis.server.entity.ChildTable">
		<id column="id" property="id" jdbcType="VARCHAR" />
		<result column="parent_id" property="parentId" jdbcType="VARCHAR" />
		<result column="name" property="name" jdbcType="INTEGER" />
	</resultMap>

	<!--
	 	@Data // lombok 插件
		@EqualsAndHashCode(callSuper = true)
		@Accessors(chain = true)
		public class MasterAndChildList implements Serializable {

			private static final long serialVersionUID = 1L;

			/**
			 * ID
			 */
			private Integer departmentType;

			/**
			 * 子表数据列表
			 */
			private List<ChildTable> childList;

		}

	 -->

	<!--
		tip: 复用现存标签时若位于相同mapper文件可直接使用 resultMap 的 id 属性引用,跨文件时需要指定 namespace 属性才可正常引用

		extends: 继承,可继承其他 resultMap 并加以扩展
		association: 复用现存的 resultMap,适用于对应的属性为 单 JavaBean 时,使用 javaType 指定Java类型
		collection: 复用现存的 resultMap,适用于对应的属性为 JavaBean集合 时,使用 ofType 指定Java类型
		columnPrefix: 只将该属性指定前缀的属性赋值给当前 resultMap,存在多层嵌套时每进入一层就会将本层前缀截取掉。
			如下面的mapper文件中,外层的 fullMemberMap 前缀为 child_,经本次筛选 child_id -> id,
			内层的 com.imis.server.mapper.DemoMapper.Child_BaseResultMap 前缀为 child_,经本次筛选 child_id -> id,最终被赋值给 ChildTable.id
			所以只有形如 child_id 的字段才会最终进入 com.imis.server.mapper.DemoMapper.Child_BaseResultMap 的取值范围中

		若是不复用只是单纯嵌套,则可以直接将三个类写在一个 resultMap 标签内实现

	-->

	<resultMap id="BaseResultMap" extends="com.imis.server.mapper.DemoMapper.Master_BaseResultMap" type="com.imis.server.entity.MasterAndChildList">
		<collection property="childList" javaType="java.util.List" ofType="com.dtqy.server.entity.ChildTable" resultMap="com.imis.server.mapper.DemoMapper.Child_BaseResultMap" columnPrefix="child_"></collection>
	</resultMap>

	<sql id="Master_Base_Column_List">
		master_table.id,
		master_table.name
	</sql>

	<sql id="Child_Base_Column_List">
		child_table.id AS child_id,
		child_table.parent_id AS child_parent_id,
		child_table.name AS child_name
	</sql>

	<sql id="Master_Example_Where_Clause">
		<where>
			<trim prefix="" suffix="" prefixOverrides="">
				<if test="parameter != null">
					<if test="parameter.id != null and parameter.id != ''">
						<!-- 主键 -->
						AND master_table.id = #{parameter.id, jdbcType=VARCHAR}
					</if>
					<if test="parameter.name != null and parameter.name != ''">
						<!-- 名称 -->
						<![CDATA[ AND master_table.name LIKE #{parameter.name, jdbcType=VARCHAR} ||'%' ]]>
					</if>
				</if>
			</trim>
		</where>
	</sql>

	<sql id="Child_Example_Where_Clause">
		<where>
			<trim prefix="" suffix="" prefixOverrides="">
				<if test="parameter != null">
					<if test="parameter.childId != null and parameter.childId != ''">
						<!-- 主键 -->
						AND child_table.id = #{parameter.childId, jdbcType=VARCHAR}
					</if>
					<if test="parameter.childName != null and parameter.childName != ''">
						<!-- 名称 -->
						<![CDATA[ AND child_table.name LIKE #{parameter.childName, jdbcType=VARCHAR} ||'%' ]]>
					</if>
				</if>
			</trim>
		</where>
	</sql>

	<!-- 主表统计查询 -->
	<select id="count" resultType="java.lang.Integer" parameterType="java.util.Map">
		SELECT
			COUNT(1)
		FROM
			master_table
		<include refid="Master_Example_Where_Clause" />
	</select>

	<!-- 主表分页查询 -->
	<select id="queryList" resultMap="BaseResultMap" parameterType="java.util.Map">
		SELECT
			master_table.*,
			<include refid="Detail_Base_Column_List" />
		FROM
			(
				SELECT
					<include refid="Master_Base_Column_List" />
				FROM
					master_table
				<include refid="Master_Example_Where_Clause" />
				<if test="parameter.pageNumber != null ">
					LIMIT ${(parameter.pageNumber != 0 ? (parameter.pageNumber - 1) : parameter.pageNumber) * parameter.pageSize}, ${parameter.pageSize}
				</if>
			)
			LEFT JOIN child_table ON master_table.id = child_table.parent_id
			<include refid="Child_Example_Where_Clause" />
		ORDER BY
			master_table.name DESC,
			child_table.name ASC
	</select>

	<!-- 删除主表\从表数据 -->
	<delete id="deleteById" parameterType="java.lang.String">
		DELETE
			master_table, child_table
		FROM
			master_table LEFT JOIN child_table ON master_table.id = child_table.parent_id
		WHERE
			master_table.id = #{id, jdbcType=VARCHAR};
	</delete>

	<!-- ID 查询主表从表数据 -->
	<select id="getById" resultMap="BaseResultMap" parameterType="java.lang.String">
		SELECT
			master_table.*,
			<include refid="Detail_Base_Column_List" />
		FROM
			(
				SELECT
					<include refid="Master_Base_Column_List" />
				FROM
					master_table
				WHERE
					master_table.id = #{id, jdbcType=VARCHAR};
				LIMIT 1
			)
			LEFT JOIN child_table ON master_table.id = child_table.parent_id
		ORDER BY
			child_table.name ASC
	</select>

	<!-- 参数查询单条主表数据 -->
	<select id="getByParameter" resultMap="BaseResultMap" parameterType="java.util.Map">
		SELECT
			master_table.*,
			<include refid="Detail_Base_Column_List" />
		FROM
			(
				SELECT
					<include refid="Master_Base_Column_List" />
				FROM
					master_table
				<include refid="Master_Example_Where_Clause" />
				LIMIT 1
			)
			LEFT JOIN child_table ON master_table.id = child_table.parent_id
			<include refid="Child_Example_Where_Clause" />
		ORDER BY
			child_table.jd_rank ASC
	</select>

</mapper>

参考资料:MyBatis resultMap 标签 继承复用嵌套

### 若依框架实现业务流程开发教程 若依框架是一个基于Spring Boot和MyBatis的开源项目,提供了快速开发的能力。其核心功能之一是代码生成器,能够自动生成适用于不同场景的代码模板,从而提升开发效率。 #### 使用若依框架实现业务流程的关键步骤说明 1. **理解框架结构** 若依框架采用前后端分离架构设计,前端基于Vue.js或Vue3,而后端则依托于Spring Boot和MyBatis[^2]。开发者需熟悉这些技术栈的基本原理及其在若依中的具体实现方式。 2. **利用代码生成器** 若要实现特定业务逻辑,可以通过若依内置的代码生成器完成基础代码的自动化构建。该工具支持多种模板类型,如单表、树表和主子表(一对多)。这使得即使面对复杂的业务需求也能迅速搭建起初步模型。 3. **配置数据库环境** 在实际操作前,需要确保MySQL数据库已正确安装并运行正常。同时按照官方文档指导,在本地环境中设置好对应的连接参数以及初始化必要的SQL脚本文件[^3]。例如: ```sql CREATE DATABASE ruoyi DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE ruoyi; -- 创建用户表示例 CREATE TABLE sys_user ( user_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID', username VARCHAR(30) NOT NULL COMMENT '用户名', password VARCHAR(100) DEFAULT '' COMMENT '密码', PRIMARY KEY (user_id) ) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表'; ``` 4. **导入SQL语句至数据库** 可以选择通过IDEA自带的MySQL可视化管理工具或者其他第三方客户端软件执行上述DDL/DML命令来完成数据准备阶段的工作。这样做的好处是可以直观查看整个过程并对可能出现的问题及时调整优化策略。 5. **定制化修改默认行为** 虽然自动化的部分已经大大减少了手动编码量,但在某些特殊情况下仍可能需要针对具体情况做进一步适配改动。比如增加额外字段校验规则或者改变原有API接口返回格式等等。此时就需要深入研究源码内部机制以便灵活应对各种突发状况。 6. **测试验证最终效果** 完成以上各环节之后不要忘记进行全面的功能性和性能方面的检测评估工作。只有经过充分检验后的版本才能真正投入生产使用当中去发挥价值所在。 ```java // 示例:定义一个新的Controller用于展示新增加的功能模块 @RestController @RequestMapping("/customFeature") public class CustomFeatureController { @Autowired private ICustomService customService; @GetMapping("/{id}") public ResponseEntity<?> getDetail(@PathVariable Long id){ try{ Object result = this.customService.findById(id); return new ResponseEntity<>(result, HttpStatus.OK); }catch(Exception e){ log.error("Error occurred while fetching detail",e); return new ResponseEntity<>("Failed to load data.",HttpStatus.INTERNAL_SERVER_ERROR); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叁金Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值