MyBatis 注解操作与 XML 配置增删改查全流程实现代码

 更新时间:2026年01月22日 16:43:35   作者:独断万古他化  
本文介绍了MyBatis,它是一款轻量级的持久层框架,能简化JDBC冗余代码,支持自定义SQL与对象映射,并兼顾开发效率与灵活性,通过实例代码介绍了MyBatis 注解操作与 XML 配置增删改查全流程实现代码,感兴趣的朋友一起看看吧

一、Mybatis 初识

1.1 Mybatis 定义

  • MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

web应用程序⼀般分为三层,即:Controller、Service、Dao。持久层(Dao)是数据访问层,用来操作数据库。

而 MyBatis 是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库工具。

1.2 入门案例

  1. 数据准备:
-- 创建表[用户表]
DROP TABLE IF EXISTS user_info;
CREATE TABLE `user_info` (
        `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
        `username` VARCHAR ( 127 ) NOT NULL,
        `password` VARCHAR ( 127 ) NOT NULL,
        `age` TINYINT ( 4 ) NOT NULL,
        `gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-女 0-默认',
        `phone` VARCHAR ( 15 ) DEFAULT NULL,
        `delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
        `create_time` DATETIME DEFAULT now(),
        `update_time` DATETIME DEFAULT now() ON UPDATE now(),
        PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; 
-- 添加用户信息
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );
  1. 创建对应实体类:
@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}
  1. 配置数据库连接字符串
    Mybatis 中配置连接数据库,需要数据库相关参数配置
    Mysql 驱动类
    登录名
    密码
    数据库连接字符串
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  1. 持久层代码
@Mapper
public interface UserInfoMapper {
		@Select("select * from user_info")
    List<UserInfo> selectAll();
}
  • 持久层接口的命名规范一般为 XxxMapper
  • @Mapper 注解:用于标识这是 MyBatis 中的 Mapper 接口
  • 程序运行时,框架会自动为该接口生成实现类对象(代理对象),并将其交给 Spring 的 IOC 容器管理
  • @Select 注解:代表一个 select 查询,注解内的内容就是对应方法的具体 SQL 实现
  1. 单元测试
    在创建出来的SpringBoot工程中,在src下的test目录下,已经自动创建好了测试类,可以直接使用这个测试类来进行测试。
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void selectAll() {
        List<UserInfo> userInfos = userInfoMapper.selectAll();
        userInfos.forEach(System.out::println);
    }
}

运行结果如下:

二、Mybatis 基础操作

下面详细讲述MyBatis的增,删,改,查操作。

2.1 打印日志

  • 在 MyBatis 中,我们可以借助日志查看 SQL 语句的执行、执行时传递的参数,以及最终的执行结果
  • 日志功能只需在配置文件中进行配置即可启用
#  配置打印MyBatis⽇志
mybatis:
  configuration: 
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl		

重新运行可以得到如下内容,传递参数和执行结果:

2.2 参数传递

需求:根据id 查询用户,sql select * from user_info where id = ?

  • 问题:如果 SQL 语句中的 id 写为固定数值(如 id=4),则只能查询固定对应的数据,无法满足动态查询的需求。
  • 解决方案:在 selectById 方法中添加参数 (id),将方法的参数传递给 SQL 语句。
  • 具体用法:使用 #{} 的方式获取方法中的参数,从而让 SQL 支持动态数值。
	@Select("select id,username,`password`,age,gender,phone,delete_flag," +
            "create_time,update_time from user_info where id= #{id}")
    UserInfo selectById(Integer id);

如果mapper接口方法形参只有⼀个普通类型的参数,#{…}里面的属性名可以随便写,如:#{id}、#{value}。建议和参数名保持⼀致。但是参数有多个时,必须和参数名保持一致。

测试用例:

	@Test
    void selectById() {
        UserInfo userInfo = userInfoMapper.selectById(1);
        System.out.println(userInfo);
    }

结果:

也可以通过 @Param 设置参数的别名,如果使用 @Param 设置别名,#{...} 里面的属性名必须和 @Param 设置的一样,例:

	@Select("select id,username,`password`,age,gender,phone,delete_flag," +
            "create_time,update_time from user_info where id= #{id}")
    UserInfo selectById(@Param("id") Integer id);

2.3 增(Insert)

	@Insert("insertinto user_info (username, `password`, age, gender)" +
            "values (#{username},#{password},#{age},#{gender})")
    Integer insertUser(UserInfo userInfo);

可以直接使用UserInfo 对象的属性名来获取参数。也可以写出所有属性来获取参数。
此时返回的是执行的行数。

测试:

	@Test
    void insertUser() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("java1");
        userInfo.setPassword("java1");
        userInfo.setAge(20);
        userInfo.setGender(1);
        Integer result = userInfoMapper.insertUser(userInfo);
        log.info("影响行数:{}",result);
    }

新增之后可以刷新数据库查看执行结果。

如果设置了 @Param 属性,#{…}需要使用 参数.属性来获取
@Insert("insert INTO user_info (username, password, age, gender) values (#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender})") Integer insertUser2(@Param("userInfo") UserInfo userInfo);

  • 返回主键 @Options
    Insert 语句默认返回的是受影响的行数
    但有些情况下,数据插入之后,还需要有后续的关联操作,需要获取到新插入数据的 id。如果想要拿到 id ,需要在Mapper 接口的方法上添加一个注解 @Options。
	@Options(useGeneratedKeys = true,keyProperty = "id") // 获得自增ID,通过注解
    @Insert("insertinto user_info (username, `password`, age, gender)" +
            "values (#{username},#{password},#{age},#{gender})")
    Integer insertUser(UserInfo userInfo);
  • useGeneratedKeys:这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false
  • keyProperty:指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset
  • 注意:设置 useGeneratedKeys=true 之后,方法返回值依然是受影响的行数,自增 id 会设置在上述 keyProperty 指定的属性中。

2.4 删(Delete)

Mapper 接口:

	@Delete("delete from user_info where id = #{id}")
    Integer deleteUserById(Integer id);

测试:

	@Test
    void deleteUserById() {
        Integer result = userInfoMapper.deleteUserById(11);
    }

2.5 改(Update)

Mapper 接口:

	@Update("update user_info set gender = #{gender} where id = #{id}")
    void updateUserById(Integer gender,Integer id);

测试:

	@Test
    void updateUserById() {
        userInfoMapper.updateUserById(0,11);
    }

2.6 查(Select)

在上面查询时发现,有几个字段是没有赋值的,只有 Java 对象属性和数据库字段一模一样时,才会进行赋值。查询结果:

从运行结果上可以看到,我们SQL语句中,查询了delete_flag, create_time, update_time,但是这几个属性却没有赋值。

原因分析:
当自动映射查询结果时,MyBatis会获取结果中返回的列名并在Java类中查找相同名字的属性(忽略大小写)。这意味着如果发现了ID列和id属性,MyBatis会将列ID的值赋给id属性

解决办法:

  1. 起别名
  2. 结果映射
  3. 开启驼峰命名

2.6.1 起别名

在SQL 语句中,给列名起别名,保持别名和实体类属性名一样。

    @Select("SELECT id,username,`password`,age,gender,phone,delete_flag as deleteFlag, " +
            "create_time as createTime, update_time as updateTime " +
            "from user_info") //起别名
    List<UserInfo> selectAll();

2.6.2 结果映射

使用Spring 提供的注解 @Results :

    @Results(id = "BaseMap",value = {
            @Result(column = "delete_flag",property = "deleteFlag"),
            @Result(column = "create_time",property = "createTime"),
            @Result(column = "update_time",property = "updateTime"),
    })  //通过注解映射
    @Select("select id,username,`password`,age,gender,phone,delete_flag," +
            "create_time,update_time from user_info")
    List<UserInfo> selectAll();

如果其他SQL 需要复用这个映射关系,可以给这个Results 定义一个名称,如上id = "BaseMap" ,使用 @ResultMap 注解来复用即可,例:

    @ResultMap("BaseMap")
    @Select("select id,username,`password`,age,gender,phone,delete_flag," +
            "create_time,update_time from user_info where id= #{id}")
    UserInfo selectById(@Param("id") Integer id);

2.6.3 开启驼峰命名

通常数据库列使用蛇形命名法进行命名(下划线分割各个单词),而 Java 属性一般遵循驼峰命名法约定。为了在这两种命名方式之间启用自动映射,需要将 mapUnderscoreToCamelCase 设置为 true

mybatis:
  configuration:
    map-underscore-to-camel-case: true #配置驼峰自动转换

驼峰命名规则:abc_xyz => abcXyz

  • 表中字段名:abc_xyz
  • 类中属性名:abcXyz

Java 代码不做任何处理

通过上面三个方法后,执行查询发现所有字段都可以查询到数据,全部进行正确赋值:

三、Mybatis XML 配置文件

Mybatis 的开发有两种方式:

  1. 注解
  2. XML配置文件

3.1 配置

需要进行数据库连接字符串配置和Mybatis 的 XML 文件配置。

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: whx041223
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml # 配置 mybatis xml 文件路径;classpath 对应resources
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #  配置打印MyBatis⽇志
    map-underscore-to-camel-case: true #配置驼峰⾃动转换

3.2 入门案例

进行持久层代码编写

  1. 方法定义 Interface,添加Mapper 接口
@Mapper
public interface UserInfoXmlMapper {
    List<UserInfo> selectAll();
}
  1. 方法实现,添加UserInfoXMLMapper.xml
<?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.whx.mybatis.mapper.UserInfoXmlMapper">
    <select id="selectAll" resultType="com.whx.mybatis.entity.UserInfo">
        select id,username,`password`,age,gender,phone,delete_flag,
        create_time,update_time from user_info
    </select>
</mapper>

标签的说明:

  • <mapper> 标签:需要指定 namespace 属性,表示命名空间,值为 mapper 接口的全限定名,包括全包名.类名。
  • <select> 查询标签:是用来执行数据库的查询操作的:
    • id:是和 Interface(接口)中定义的方法名称一样的,表示对接口的具体实现方法。
    • resultType:是返回的数据类型,也就是开头定义的实体类。

3.1 增(Insert)

接口:

	Integer insertUser(UserInfo userInfo);

方法实现:

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into user_info (username, `password`, age, gender)
        values (#{username},#{password},#{age},#{gender})
    </insert>

返回自增id,接口定义不变,在Mapper.xml 中设置useGeneratedKeys和keyProperty属性。

如果使用 @Param 设置参数名,使用方法和注解类似:
接口:

	Integer insertUser(@Param("userInfo") UserInfo userInfo);

方法实现:

<insert id="insertUser">
        insert INTO user_info (username, `password`, age, gender)
        values (#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender})
    </insert>

3.2 删(Delete)

接口:

	Integer deleteUserById(Integer id);

方法实现:

<delete id="deleteUserById">
        delete from user_info where id = #{id}
    </delete>

3.3 改(Update)

接口:

	void updateUserById(Integer gender,Integer id);

方法实现:

<update id="updateUserById">
        update user_info set gender = #{gender} where id = #{id}
    </update>

3.4 查(Select)

和注解方式一样,使用XML方式查询也存在数据封装的问题。

结果显示:deleteFlag,createTime,updateTime也没有进行赋值。
解决办法和注解一样:

  1. 起别名
  2. 结果映射
  3. 开启驼峰命名

其中1,3的解决办法和注解一样,结果映射在XML中的方法:

    <resultMap id="BaseMapXml" type="com.whx.mybatis.entity.UserInfo">
        <id property="id" column="id"></id>
        <result property="deleteFlag" column="delete_flag"></result>
        <result property="createTime" column="create_time"></result>
        <result property="updateTime" column="update_time"></result>
    </resultMap>
	<select id="selectAll" resultMap="BaseMapXml">
        select id,username,`password`,age,gender,phone,delete_flag,
        create_time,update_time from user_info
    </select>

解析:

总结:
本文围绕 MyBatis 轻量级持久层框架展开,总结其核心使用要点。MyBatis 通过注解或 XML 配置简化 JDBC 冗余代码,支持自定义 SQL 与对象映射,兼顾开发效率与灵活性。入门环节涵盖数据库准备、实体类定义、配置编写、Mapper 接口开发及单元测试,可快速搭建运行环境。基础操作中,日志配置能查看 SQL 执行细节,#{}实现单参数、多参数等场景的动态绑定,增删改查操作可通过注解或 XML 配置获取自增主键,查询结果映射提供起别名、resultMap、驼峰命名转换三种方案,解决数据库与 Java 命名适配问题。XML 配置适配复杂 SQL 场景,掌握这些核心点即可应对日常持久层开发。

到此这篇关于MyBatis 注解操作与 XML 配置增删改查全流程实现代码的文章就介绍到这了,更多相关MyBatis 注解与 XML 配置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 利用Spring框架为自己的校园卡充值(推荐)

    利用Spring框架为自己的校园卡充值(推荐)

    这篇文章主要介绍了利用Spring框架为自己的校园卡充值,本次实验主要运用了Spring的控制反转(IOC)和依赖注入(DI)等知识,通过利用Spring框架编写Java程序,实现学生卡的单次充值,如需对学生卡进行多次充值,可将部分代码修改即可实现,需要的朋友可以参考下
    2022-10-10
  • Java进阶之SPI机制详解

    Java进阶之SPI机制详解

    Java SPI机制在很多大型中间建码,例如Dubbo中均有采用,属于高级Java开发的进阶必备知识点,务必要求掌握.文中有非常详细的代码示例及解释,需要的朋友可以参考下
    2021-05-05
  • Java编程实现月食简单代码分享

    Java编程实现月食简单代码分享

    这篇文章主要介绍了Java编程实现月食简单代码分享,程序很简单,喜欢的朋友可以拿过去玩玩。
    2017-11-11
  • SpringBoot与Dubbo整合的方式详解

    SpringBoot与Dubbo整合的方式详解

    这篇文章主要介绍了SpringBoot与Dubbo整合的方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • 详解Java中CountDownLatch异步转同步工具类

    详解Java中CountDownLatch异步转同步工具类

    今天给大家带来的是关于Java的相关知识,文章围绕着CountDownLatch异步转同步工具类展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • Java RSA加密解密实现方法分析【附BASE64 jar包下载】

    Java RSA加密解密实现方法分析【附BASE64 jar包下载】

    这篇文章主要介绍了Java RSA加密解密实现方法,结合实例形式分析了java基于第三方类库javabase64-1.3.1.jar实现RSA加密解密功能的具体步骤与相关操作技巧,需要的朋友可以参考下
    2017-10-10
  • Java 如何快速实现一个连接池

    Java 如何快速实现一个连接池

    有没有一个通用的库可以快速实现一个线程池呢?得益于 Java 完善的生态,前人们针对这种需要开发了一个通用库:Apache Commons Pool(下文简称 ACP)。本质上来说,ACP 库提供的是管理对象池的通用能力,当然也可以用来管理连接池了!
    2021-05-05
  • Spring实战之属性覆盖占位符配置器用法示例

    Spring实战之属性覆盖占位符配置器用法示例

    这篇文章主要介绍了Spring实战之属性覆盖占位符配置器用法,结合实例形式分析了Spring属性覆盖占位符配置器相关原理、配置与使用技巧,需要的朋友可以参考下
    2019-12-12
  • 详解Alibaba Java诊断工具Arthas查看Dubbo动态代理类

    详解Alibaba Java诊断工具Arthas查看Dubbo动态代理类

    这篇文章主要介绍了Alibaba Java诊断工具Arthas查看Dubbo动态代理类 ,它可以帮助我们查看JDK或者javassist生成的动态代理类,当然,它的功能远不止此,还可以在生产环境进行诊断,需要的朋友可以参考下
    2022-04-04
  • Java并发编程(CyclicBarrier)实例详解

    Java并发编程(CyclicBarrier)实例详解

    这篇文章主要介绍了Java并发编程(CyclicBarrier)实例详解的相关资料,JAVA编写并发程序的时候,我们需要仔细去思考一下并发流程的控制,如何让各个线程之间协作完成某项工作。
    2017-07-07

最新评论