1.mybatis中的一些特殊操作

1.1批量删除

/**
* 批量删除用户信息
*/
Integer deleteUserByIds(String ids);
<!-- 批量删除用户信息 -->
<delete id="deleteUserByIds">
delete from user where id in (${ids})
</delete>
/**
* 批量删除测试
*/
@Test
public void deleteUserByIdsTest() {
String ids = "18,19,20";
Integer num = userMapper.deleteUserByIds(ids);
if (num > 0) {
System.out.println("删除成功!!");
} else {
System.out.println("删除失败!!");
}
}

1.2动态获取表名

/**
* 动态获取表名
*/
List<Map<String, Object>> getList(String tableName);
<!-- 动态获取表名-->
<select id="getList" resultType="map">
select * from ${tablename}
</select>
/**
* 动态获取表名测试
*/
@Test
public void getListTest() {
List<Map<String, Object>> list = userMapper.getList("user_demo");
list.forEach(System.out::println);
}

动态获取表名的时候需要用${}的方式获取,因为我们在传入数据的时候就是自带引号的,如果我们使用

占位符的方式传入数据的话,那么就会导致最后拼出来的sql语句长这样: select * from

‘‘user’’ 也就是两个单引号的形式,那就找不到对应的表了,所以使用${}。

1.3添加功能获取自增主键

为什么需要获取自增主键?因为我们如果删除了某个数据,但是我们的序号依旧会按照删除之前的顺序

继续增加,就会导致序号不连续,没有可读性。应用场景如下:

  1. 添加班级信息
  2. 获取新添加的班级的id
  3. 为班级分配学生,即将某学的班级id修改为新添加的班级的id

在这里插入图片描述

可以看到我们的返回值是没有获取到新增user的id的,这就导致了用户是看不到这个序号的,我们通过

Mapper.xml中的两个属性来获取到我们的自增主键:

useGeneratedKeys:表示当前添加功能实现自增的主键

keyProperty:将添加的数据的自增的主键为实体类类型的参数的属性赋值(User对象中的id属

性)

代码如下:

/**
* 添加用户信息并获取自增主键
* @param user 用户实体类
*/
void insertUserKey(User user);
<!--
添加用户信息获取自增主键
useGeneratedKeys:表示当前添加功能实现自增的主键
keyProperty:将添加的数据的自增的主键为实体类类型的参数的属性赋值(User对象中的id属性)
-->
<insert id="insertUserKey" useGeneratedKeys="true" keyProperty="id">
insert into user values (null, #{username}, #{password}, #{age}, #{sex}, #
{email})
</insert>
/**
* 添加用户信息获取自增主键测试
*/
@Test
public void insertUserTest() {
User user = new User(null, "Steve", "123456", 23, "男", "Steve@qq.com");
userMapper.insertUserKey(user);
System.out.println(user);
}

添加属性之后我们就可以获取到自增的主键了:

在这里插入图片描述

1.4自定义映射resultMap

用于解决表中的列名和实体类中属性名不一致的情况,比如我现在的列名为: emp_xxx ,这样带有下划

线的形式,但是我们的实体类中一班用驼峰命名的方式来命名我们的属性,那就回导致属性名和列名不

一致,那我们可以通过 resultMap 这个属性来自定义映射,让属性和列对应上。

在这里插入图片描述

我们新建一个数据表: emp_user :

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for emp_user
-- ----------------------------
DROP TABLE IF EXISTS `emp_user`;
CREATE TABLE `emp_user` (
`emp_id` int NOT NULL,
`emp_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL
DEFAULT NULL,
`emp_age` int NULL DEFAULT NULL,
`emp_sex` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL
DEFAULT NULL,
`emp_email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL
DEFAULT NULL,
PRIMARY KEY (`emp_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci
ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of emp_user
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;

然后随机加一些数据进去:

在这里插入图片描述

接着创建我们的实体类,生成对应的构造方法等:

public class Emp {
private Integer empId;
private String empName;
private Integer empAge;
private String empSex;
private String empEmail;
public Emp(Integer empId, String empName, Integer empAge, String empSex,
String empEmail) {
this.empId = empId;
this.empName = empName;
this.empAge = empAge;
this.empSex = empSex;
this.empEmail = empEmail;
}
public Emp() {
}
定义好我们的Mapper接口和映射文件,写一个简单的查询:
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Integer getEmpAge() {
return empAge;
}
public void setEmpAge(Integer empAge) {
this.empAge = empAge;
}
public String getEmpSex() {
return empSex;
}
public void setEmpSex(String empSex) {
this.empSex = empSex;
}
public String getEmpEmail() {
return empEmail;
}
public void setEmpEmail(String empEmail) {
this.empEmail = empEmail;
}
@Override
public String toString() {
return "Emp{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", empAge=" + empAge +
", empSex='" + empSex + '\'' +
", empEmail='" + empEmail + '\'' +
'}';
}
}

定义好我们的Mapper接口和映射文件,写一个简单的查询:

public interface EmpMapper {
/**
* 通过id查询用户
* @param empId 员工id
* @return 返回用户对象
*/
Emp getEmpById(Integer empId);
}
<mapper namespace="com.qcby.mybatis.mappers.EmpMapper">
<!-- 通过员工id查询员工信息 -->
<select id="getEmpById" resultType="emp">
select * from emp_user where emp_id = #{empId}
</select>
</mapper>

写测试类进行测试:

@Test
public void getEmpByIdTest(){
Emp emp = empMapper.getEmpById(4);
System.out.println(emp);
}

在这里插入图片描述

可以发现,我们其实查询到了一条对应的数据,但是其中的属性值并没有输出,这就是应为我们数据表

的列名和我们 Emp 实体类中的属性名不一致导致的,那么我们有以下几种解决方法:

  1. 可以通过为字段起别名的方式,保证和实体类中的属性名保持一致

在我们的映射文件中去给每一个列名起别名(IDEA2024这么智能吗???)

<mapper namespace="com.qcby.mybatis.mappers.EmpMapper">
<!-- 通过员工id查询员工信息 -->
<select id="getEmpById" resultType="emp">
select emp_id empId, emp_name empName, emp_age empAge, emp_sex
empSex, emp_email empEmail from emp_user where emp_id = #{empId}
</select>
</mapper>

在这里插入图片描述

此时再次执行查询,我们就会发现属性名可以打印出来了:

在这里插入图片描述

  1. 若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性

名符合Java的规则(使用驼峰),可以在MyBatis 的核心配置文件中设置一个全局配置信息

mapUnderscoreToCamelCase ,可以在查询表中数据时,自动将_类型的字段名转换为驼峰。

就是我们现在的情况:数据库中为 emp_xxx ,但是实体类中为 empXxx :那么我们在

MyBatisConfig中配置,注意标签在配置文件中的位置:

<settings>
<!-- 自动将_类型的字段名转换为驼峰-->
<!--<setting name="mapUnderscoreToCamelCase" value="true"/>-->
</settings>

同样可以实现相同的效果。

  1. 使用resultMap

在我们的映射文件中定义一个 resultMap ,和起别名差不多,手动的将列名和属性名一一对应:

<!-- 自定义resultMap -->
<resultMap id="empResultMap" type="emp">
<!-- 主键使用id -->
<id column="emp_id" property="empId"/>
<!-- 其他列使用result -->
<result column="emp_name" property="empName"/>
<result column="emp_age" property="empAge"/>
<result column="emp_sex" property="empSex"/>
<result column="emp_email" property="empEmail"/>
</resultMap>

结果也可以正确输出。

resultMap 标签:
id :唯一标识
type :处理映射关系的实体类的类型
常用标签:
id :处理主键映射,包含的属性: column :设置映射关系中的列名,必须是 sql 查询
的字段名(如果起了别名就写别名); property :设置映射关系中的映射属性名,必
须是实体类中的属性名
result :处理普通字段的映射,包含的属性: column :设置映射关系中的列名,必须
是 sql 查询的字段名(如果起了别名就写别名); property :设置映射关系中的映射
属性名,必须是实体类中的属性名
collction :处理一对多的关系
association :处理多对一的关系
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐