mybatis第三话 - mybatis的高端用法你会吗?

22 篇文章 0 订阅
13 篇文章 0 订阅

前面了解了springboot + mybatis的单数据源和多数据源的集成已经使用,本篇文章来聊聊mybatis的高端用法吧

1.环境搭配

1.1 pom依赖

  • 基于springboot 2.5.6,也可以参看mybatis的第一篇文章
<!--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>

1.2 yml配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.0.100:3306/demo_test?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
    username: root
    password: 123456

#mybatis资源文件扫描和其他相关配置
mybatis:
  mapperLocations: classpath:mapper/*/*.xml
  executorType: SIMPLE
  configuration:
    # 驼峰式 测试用先关闭
#    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

1.3 数据库表

user_info 用户的信息表
user_card 用户身份证表 一个用户一个身份证 一对一
user_mobile 用户手机号表 一个用户有多个手机号

-- 导出  表 demo_test.user_card 结构
CREATE TABLE IF NOT EXISTS `user_card` (
  `user_id` bigint(20) NOT NULL COMMENT '用户ID',
  `card` varchar(50) DEFAULT NULL COMMENT '身份证',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='身份证表';

-- 正在导出表  demo_test.user_card 的数据:~3 rows (大约)
DELETE FROM `user_card`;
/*!40000 ALTER TABLE `user_card` DISABLE KEYS */;
INSERT INTO `user_card` (`user_id`, `card`, `create_time`, `update_time`) VALUES
	(1, '111111', '2022-02-17 16:45:28', '2022-02-17 16:45:28');
/*!40000 ALTER TABLE `user_card` ENABLE KEYS */;

-- 导出  表 demo_test.user_info 结构
CREATE TABLE IF NOT EXISTS `user_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL COMMENT '名称',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

-- 正在导出表  demo_test.user_info 的数据:~3 rows (大约)
DELETE FROM `user_info`;
/*!40000 ALTER TABLE `user_info` DISABLE KEYS */;
INSERT INTO `user_info` (`id`, `name`, `age`, `create_time`, `update_time`) VALUES
	(1, '张三', 22, '2022-02-17 16:45:01', '2022-02-17 16:47:21');
/*!40000 ALTER TABLE `user_info` ENABLE KEYS */;

-- 导出  表 demo_test.user_mobile 结构
CREATE TABLE IF NOT EXISTS `user_mobile` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `userId` bigint(20) DEFAULT NULL COMMENT '用户id',
  `mobile` varchar(50) NOT NULL COMMENT '手机号',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `userId` (`userId`,`mobile`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='用户手机表';

-- 正在导出表  demo_test.user_mobile 的数据:~2 rows (大约)
DELETE FROM `user_mobile`;
/*!40000 ALTER TABLE `user_mobile` DISABLE KEYS */;
INSERT INTO `user_mobile` (`id`, `userId`, `mobile`, `create_time`, `update_time`) VALUES
	(1, 1, '13011112222', '2022-02-17 16:45:51', '2022-02-17 16:45:51'),
	(2, 1, '13011112223', '2022-02-17 16:45:51', '2022-02-17 16:47:02'),
	(3, 1, '13011112224', '2022-02-17 16:45:51', '2022-02-17 16:47:02');

1.4 测试代码

	@Resource
    TestMapper testMapper;
    
	@GetMapping("/data/selectBean")
    public Object selectBean(@RequestParam(required = false) Long id) {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(id);
        List<UserInfo> userInfos = testMapper.selectBean(userInfo);
        return userInfos;
    }

1.5 java bean

分别对user_info、user_card、user_mobile生成实体bean,并添加getter、setter方法
只贴下user_info的bean,后面一对一,一对多查询用

@Data
public class UserInfo {
    Long id;
    String name;
    Integer age;
    //个人的身份证,一对一关系
    UserCard userCard;
    //个人的手机号 一对多关系
    Set<UserMobile> userMobiles;
    String createTime;
    String updateTime;
}

2. resultMap 映射

2.1 直接映射

  • xml文件,注意传参的parameterType和出参的resultType
<select id="selectBean" parameterType="com.example.demo.entity.UserInfo"
resultType="com.example.demo.entity.UserInfo">
	select * from user_info where id = #{id}
</select>
  • 测试结果输出
[{
	"id": 1,
	"name": "张三",
	"age": 22,
	"userCard": null,
	"userMobileList": null,
	"createTime": null,
	"updateTime": null
}]

结果可以看到,原本表中的createTime和updateTime有值的,但也输出是空。

解决方法:

  1. 打开yml里面的驼峰式配置 map-underscore-to-camel-case: true
  2. 使用自定义的映射resultMap

接下来方便测试,从这里打开驼峰式的配置

2.2 自定义映射map

  • xml代码做如下修改
//例如这个xml下有很多个查询都需要用到userInfo,就可以抽离出来使用
//id 别名的意思 需保持唯一 type:映射到javabean中的实体类
<resultMap id="userInfoMap" type="com.example.demo.entity.UserInfo">
	//id 主键 column/数据库中的列名 property/对应实体类中的列名
	<id property="id" column="id"/>
	<result property="name" column="name"/>
	<result property="age" column="age"/>
	<result property="createTime" column="create_time"/>
	<result property="updateTime" column="update_time"/>
</resultMap>

//这里的出参就要使用resultMap了 指向上面的id
<select id="selectBean" parameterType="com.example.demo.entity.UserInfo"
		 resultMap="userInfoMap">
	select * from user_info where id = #{id}
</select>
  • 测试结果输出
[{
	"id": 1,
	"name": "张三",
	"age": 22,
	"userCard": null,
	"userMobileList": null,
	"createTime": "2022-02-17 16:45:01",
	"updateTime": "2022-02-17 16:47:21"
}]

user_Info表中的数据都能看到了,接下来看看userCard一对一的扩展该怎么实现

3. 一对一数据查询

3.1 关联实现

<resultMap id="userInfoMap" type="com.example.demo.entity.UserInfo">
	<id property="id" column="id"/>
	<result property="name" column="name"/>
	<result property="age" column="age"/>
	<result property="createTime" column="create_time"/>
	<result property="updateTime" column="update_time"/>
	<association property="userCard" javaType="com.example.demo.entity.UserCard">
		<id property="userId" column="user_id"/>
		<result property="card" column="card"/>
		<result property="createTime" column="create_time"/>
		<result property="updateTime" column="update_time"/>
	</association>
</resultMap>


<select id="selectBean" parameterType="com.example.demo.entity.UserInfo"
		resultMap="userInfoMap">
	select * from user_info u
	left join user_card uc on u.id=uc.user_id
	where u.id = #{id}
</select>
  • 测试结果输出
[{
	"id": 1,
	"name": "张三",
	"age": 22,
	"userCard": {
		"userId": 1,
		"card": "111111",
		"createTime": "2022-02-17 16:45:01",
		"updateTime": "2022-02-17 16:47:21"
	},
	"userMobileList": null,
	"createTime": "2022-02-17 16:45:01",
	"updateTime": "2022-02-17 16:47:21"
}]

有个很明显的问题,如果两张表存在相同的字段,mysql查询会自动去掉后者。这种情况需要建立很多的别名来使用
如果这种满足不了需求,还可以用下面这种方法实现

3.2 主键查询实现

通过执行另外一个SQL映射语句来返回预期的复杂类型

  • xml代码修改
<resultMap id="userInfoMap" type="com.example.demo.entity.UserInfo">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="age" column="age"/>
		<result property="createTime" column="create_time"/>
		<result property="updateTime" column="update_time"/>
		//关联查询 property对应实体类中的userCard列 
		//使用当前id列的值在进行查询 对应的sql查询id selectUserCard
		<association property="userCard" column="id" select="selectUserCard">
			//下面的映射大同小异
			<id property="userId" column="user_id"/>
			<result property="card" column="card"/>
			<result property="createTime" column="create_time"/>
			<result property="updateTime" column="update_time"/>
		</association>
	</resultMap>

	<select id="selectBean" parameterType="com.example.demo.entity.UserInfo"
			resultMap="userInfoMap">
		select * from user_info where id = #{id}
	</select>
	//单独的查询,其他业务可以用
	<select id="selectUserCard" parameterType="Long" resultType="com.example.demo.entity.UserCard">
		select * from user_card where user_id=#{id}
	</select>
  • 测试结果输出
[{
	"id": 1,
	"name": "张三",
	"age": 22,
	"userCard": {
		"userId": 1,
		"card": "111111",
		"createTime": "2022-02-17 16:45:28",
		"updateTime": "2022-02-17 16:45:28"
	},
	"userMobileList": null,
	"createTime": "2022-02-17 16:45:01",
	"updateTime": "2022-02-17 16:47:21"
}]

结果可以看出,一对一的需求实现了,接下来分析一对多的

3. 一对多数据查询

  • xml代码修改
<resultMap id="userInfoMap" type="com.example.demo.entity.UserInfo">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="age" column="age"/>
		<result property="createTime" column="create_time"/>
		<result property="updateTime" column="update_time"/>
		//以id列的值再进行一次查询 sql id为selectUserMobile
		<collection property="userMobiles" column="id" select="selectUserMobile">
			<id property="userId" column="user_id"/>
			<result property="mobile" column="mobile"/>
			<result property="createTime" column="create_time"/>
			<result property="updateTime" column="update_time"/>
		</collection>
	</resultMap>

	<!--left join user_card uc on u.id=uc.user_id-->
	<select id="selectBean" parameterType="com.example.demo.entity.UserInfo"
			resultMap="userInfoMap">
		select * from user_info u where u.id = #{id}
	</select>

	<select id="selectUserMobile" parameterType="Long" resultType="com.example.demo.entity.UserMobile">
		select * from user_mobile where user_id=#{id}
	</select>
  • 测试结果输出
[{
	"id": 1,
	"name": "张三",
	"age": 22,
	"userCard": null,
	"userMobiles": [{
		"userId": 1,
		"mobile": "13011112223",
		"createTime": "2022-02-17 16:45:51",
		"updateTime": "2022-02-17 16:47:02"
	}, {
		"userId": 1,
		"mobile": "13011112224",
		"createTime": "2022-02-17 16:45:51",
		"updateTime": "2022-02-17 16:47:02"
	}, {
		"userId": 1,
		"mobile": "13011112222",
		"createTime": "2022-02-17 16:45:51",
		"updateTime": "2022-02-17 16:45:51"
	}],
	"createTime": "2022-02-17 16:45:01",
	"updateTime": "2022-02-17 16:47:21"
}]

以上均为作者在项目中所用过的,还想了解其他的用法的自行了解哦
以上就是本章的全部内容了。

上一篇:mybatis第二话 - mybatis,多数据源的快乐你懂吗?
下一篇:mybatis第四话 - 让我们一层一层来剥开mybatis的心,源码分析

及时当勉励,岁月不待人

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值