经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MyBatis » 查看文章
MyBatis与其使用方法讲解
来源:cnblogs  作者:ihav2carryon  时间:2025/3/7 9:09:51  对本文有异议

ORM

在讲解Mybatis之前,我们需了解一个概念ORM(Object-Relational Mapping)对象关系映射,其是数据库与Java对象进行映射的一个技术.通过使用ORM,我们可以不用编写负责的Sql语句,而是通过操作对象来实现增删改查操作

缺优分析

  • 优点
    • 提高开发效率,减少代码的重复性和维护成本
    • 增加代码的可读性,降低复杂度
    • 对数据库查询的细节进行抽象,隐藏了sql语句
  • 缺点
    • 在进行多表联查时,或存在where条件时,ORM语句会变得复杂

MyBatis

  • mybatis是一个支持自定义SQL的持久层框架,通过XML文件来实现SQL配置和数据映射,MyBatis允许开发者手动编写SQL语句,提高灵活性

Mybatis通过mapper文件,将sql查询和Java对象绑定到一起,简化了JDBC代码的编写,手动设置参数,获取结果集的工作

MyBatis的工作流程

  • 其分为以下几步

MyBatis的基本使用

环境准备

  • 引入依赖包:
  1. <!--springboot的mybatis >
  2. <dependency>
  3. <groupId>org.mybatis.spring.boot</groupId>
  4. <artifactId>mybatis-spring-boot-starter</artifactId>
  5. <version>3.0.3</version>
  6. </dependency>
  7. <!-- MySQL 连接器 -->
  8. <dependency>
  9. <groupId>mysql</groupId>
  10. <artifactId>mysql-connector-java</artifactId>
  11. <version>8.0.23</version>
  12. </dependency>
  • 创建mybatis配置文件(mybatis-config.xml)
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
  3. <configuration>
  4. <!-- mybatis环境 -->
  5. <environments default="mysql">
  6. <environment id="mysql">
  7. <!-- 配置事务的类型 -->
  8. <transactionManager type="JDBC"></transactionManager>
  9. <!-- 配置数据源(连接池) -->
  10. <dataSource type="POOLED">
  11. <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
  12. <property name="url" value="jdbc:mysql://localhost:3306/数据库名称?userSSL=false&amp;serverTimezone=Asia/Shanghai"/>
  13. <property name="username" value="帐号"/>
  14. <property name="password" value="密码"/>
  15. </dataSource>
  16. </environment>
  17. </environments>
  18. <!-- mybatis映射配置位置 -->
  19. <!-- 按模块映射不同的配置文件,让配置文件看起来更简洁 -->
  20. <mappers>
  21. <mapper resource="映射配置文件全路径"></mapper>
  22. </mappers>
  23. </configuration>
  • springboot中的application.yml
  1. mybatis:
  2. # mapper配置文件
  3. mapper-locations: classpath:mapper/*.xml
  4. # resultType别名,没有这个配置resultType包名要写全,配置后只要写类名
  5. type-aliases-package: com.mashang.xiaomistore.domain
  6. configuration:
  7. #下划线自动转驼峰
  8. map-underscore-to-camel-case: true
  • 创建Mapper映射文件
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.company.mapper.StudentMapper">
  4. <select id="queryAll" resultType="com.company.entity.Student">
  5. SELECT * FROM student
  6. </select>
  7. </mapper>

  • 创建Mapper接口:
  1. public interface StudentMapper {
  2. List<Student> queryAll();
  3. }

MyBatis日志配置

  • 引入SpringBoot中的log4j
  1. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2 -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-log4j2</artifactId>
  5. <version>3.4.3</version>
  6. </dependency>
  • 在SpringBoot中在application.ymlmybatis配置项中进行配置
  1. mybatis:
  2. configuration:
  3. log-impl: org.apache.ibatis.logging.log4j.Log4jImpl
  • 配置log4j.properties文件
  1. ### 设置###
  2. log4j.rootLogger = debug,stdout,D,E
  3. ### 输出信息到控制抬 ###
  4. log4j.appender.stdout = org.apache.log4j.ConsoleAppender
  5. log4j.appender.stdout.Target = System.out
  6. log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
  7. log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
  8. ### 输出DEBUG 级别以上的日志到=D://logs/error.log ###
  9. log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
  10. log4j.appender.D.File = D://logs/log.log
  11. log4j.appender.D.Append = true
  12. log4j.appender.D.Threshold = DEBUG
  13. log4j.appender.D.layout = org.apache.log4j.PatternLayout
  14. log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
  15. ### 输出ERROR 级别以上的日志到=D://logs/error.log ###
  16. log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
  17. log4j.appender.E.File =D://logs/error.log
  18. log4j.appender.E.Append = true
  19. log4j.appender.E.Threshold = ERROR
  20. log4j.appender.E.layout = org.apache.log4j.PatternLayout
  21. log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
  • 一个基本的mybatis的XML模板如下

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    4. <mapper namespace="com.example.mapper.UserMapper">
    5. <!-- CRUD 配置 -->
    6. </mapper>

CURD实现

select查询

  • 使用<select>标签实现基本查询

    1. <select id ="getUserById" resultType="com.company.domain.entity.User">
    2. SELECT * FORM user
    3. </select>
    • id:对应Mapper接口中的方法名,必须一致
    • resultType:指定返回结果映射到哪个Java类
  • 传参#{}${}的区别

    • #{}的特点
      • 事先进行预编译:使用#{}的参数会被Mybatis当作JDBC中的?占位符
      • 防止sql注入:由于会事先进行预编译,Mybatis能够防止Sql注入
      • 类型转换:会根据参数类型进行适当的类型转换
    • ${}的特点
      • 字符串拼接:&{}直接将字符串进行替换,相当于在Sql中直接拼接传入的参数
      • 存在sql注入的风险:没有预编译,会引发sql注入问题
  • 多条件查询

    1. <select id="getUserByNameAndAge" resultType="User">
    2. SELECT * FROM user
    3. WHERE name = #{name} AND age = #{age}
    4. </select>
  • 模糊查询

    1. <select>
    2. SELECT *
    3. FROM user
    4. WHERE name LIKE CONCAT('%', #{name}, '%')
    5. </select>
    • 使用LIKE关键字和CONCAT()函数进行查询

insert插入

  • 使用<insert>标签实现基本插入操作

    1. <insert id="insertUser" parameterType="User">
    2. INSERT INTO user(name, age)
    3. VALUES (#{name}, #{age})
    4. </insert>
    • parameterType:表示入参类型
  • 实现回填自增主键

    • 使用userGeneratedKeyskeyProperty实现
    1. <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    2. INSERT INTO user (name, age)
    3. VALUES (#{name}, #{age})
    4. </insert>
    • userGeneratedKeys:表示是否启动自增
    • keyProperty:表示将生成的主键赋值给哪个java对象的哪个属性如user.id

update更新

  • 使用<update>标签实现基本更新

    1. <update id="updateUser" parameterType="User">
    2. UPDATE user
    3. SET name=#{name},
    4. age =#{age}
    5. WHERE id = #{id}
    6. </update>

delete删除

  • 使用<delete>标签基本查询

    1. <delete id="deleteUserById" parameterType="Integer">
    2. DELETE
    3. FROM user
    4. WHERE id = #{id}
    5. </delete>

传参方式

  • 多参数传参(使用@Param)

    • 当方法有多个参数时,使用@Param注解明确参数名
    1. <select id="getUserByNameAndAge" resultType="User">
    2. SELECT * FROM user
    3. WHERE name = #{name} AND age = #{age}
    4. </select>
    • Mapper接口
    1. User getUserByNameAndAge(
    2. @Param("name") String name,
    3. @Param("age") Integer age);
  • 对象参数

    • 当参数为一个Java对象时,MyBatis自动将对象属性映射到Sql语句中的占位符
    1. <insert id="insertUser" parameterType="User">
    2. INSERT INTO user (name, age)
    3. VALUES (#{name}, #{age})
    4. </insert>
    • #{name}对应user.name,#{age}对应user.age
    • Mapper接口
    1. void insertUser(User user);
  • Map参数

    • 通过Map传递多个参数或动态参数
    1. <select id="getUserByMap" resultType="User">
    2. SELECT * FROM user
    3. WHERE name = #{name} AND age = #{age}
    4. </select>
    • Mapper接口
    1. User getUserByMap(Map<String, Object> params);
  • 集合/数组参数

    • 适用于批量查询,比如WHERE id IN (…)
    1. <select id="getUsersByIds" resultType="User">
    2. SELECT * FROM user
    3. WHERE id IN
    4. <foreach collection="ids" item="id" open="(" separator="," close=")">
    5. #{id}
    6. </foreach>
    7. </select>
    • <foreach>是动态sql中的知识点等下会系统讲解
    • Mapper接口
    1. List<User> getUsersByIds(@Param("ids") List<Integer> ids);

动态sql

标签

  • <where>:生成WHERE子句,并自动判断去掉开头多余的AND/OR关键字,使sql更简洁
  • <if>:用于判断传参条件,根据条件决定是否拼接某段SQL语句,适用于传参条件不固定,只有在满足条件时接入某个子串
  1. <select id="getUserByCondition" resultType="User">
  2. SELECT * FROM user
  3. <where>
  4. <if test="name != null and name != ''">
  5. AND name LIKE CONCAT('%', #{name}, '%')
  6. </if>
  7. <if test="age != null">
  8. AND age = #{age}
  9. </if>
  10. </where>
  11. </select>
  • name为非空,会添加AND name LIKE CONCAT('%', #{name}, '%')age为非空时会添加 AND age = #{age}
  • 结合标签使用,能自动处理首个AND,使得SQL语句正确

  • 其作用在于动态拼接SQL片段前添加或去除特点字符,比如前缀,后缀,以及多余的分隔符如,
  • 常用于INSERT和UPDATE语句,避免出现多余逗号

INSERT语句

  1. <insert id="insertUserSelective" parameterType="User">
  2. INSERT INTO user
  3. <trim prefix="(" suffix=")" suffixOverrides=",">
  4. <if test="name != null">name,</if>
  5. <if test="age != null">age,</if>
  6. <if test="email != null">email,</if>
  7. </trim>
  8. VALUES
  9. <trim prefix="(" suffix=")" suffixOverrides=",">
  10. <if test="name != null">#{name},</if>
  11. <if test="age != null">#{age},</if>
  12. <if test="email != null">#{email},</if>
  13. </trim>
  14. </insert>
  • 标签包裹字段列表和对应值部分
  • suffixOverrides=”,” 表示自动去除多余的逗号,确保sql语法正确

UPDATE语句

  • <set>标签是<trim>的特性化
  1. <update id="updateUserDynamic" parameterType="User">
  2. UPDATE user
  3. <set>
  4. <if test="name != null">name = #{name},</if>
  5. <if test="age != null">age = #{age},</if>
  6. <if test="email != null">email = #{email},</if>
  7. </set>
  8. WHERE id = #{id}
  9. </update>
  • <set>标签内部原理类似<trim>,会自动去除多余逗号

  • <foreach>用于遍历集合,数组和Map,常用于批量操作或动态生成IN子句
  • 其主要属性
    • collection:集合或数组名称(可用@Param()指定对应名称,默认为listarray)
    • item:循环时每个元素的别名
    • open:循环生成sql片段的前缀
    • separator:循环时的分隔符
    • close:循环生成sql片段的后缀
  1. <select id="getUsersByIds" resultType="User">
  2. SELECT * FROM user
  3. <where>
  4. <if test="ids != null">
  5. AND id IN
  6. <foreach collection="ids" item="id" open="(" separator="," close=")">
  7. #{id}
  8. </foreach>
  9. </if>
  10. </where>
  11. </select>
  • 当ids不为null时,进入<if test="ids != null">生成的sql片段为 SELECT * FROM AND WHERE id IN(#{id},#{id},…)
  • 其中标签遍历集合ids,用逗号进行分隔,并在开头添加(括号,结尾添加)括号
  • 最终标签会去除第一个AND,使sql合法SELECT * FROM id WHERE IN(#{id},#{id},…)

MyBatis的映射

基本映射

用于单一的字段对应

  • 假设有一个user表,其中有字段id,name,age其在Java中有个简单的对应类User,其属性分别也是id,name,age那么在Mapper.xml进行select查询时

    1. SELECT id, name, age FROM user WHERE id = #{id}
  • MyBatis会将查询的结果中每一列值自动赋值给User对象中相同的属性

    • 数据库列表的id→User对象的id
    • 数据库列表的name→User对象的name
    • 数据库列表的age→User对象的age
  • 这样可能就会出现一种情况,数据库列表的列名与对象的属性名不一致,通常使用开启驼峰转换来解决→在application.yml的mybatis配置中添加如下配置:

    1. mybatis:
    2. map-underscore-to-camel-case: true

一对一映射

当查询中需要查询一个对象时

  • 现假设,数据库有两张表一个user(用户)表,另一个user_detail(用户详细信息)表,在Java中我们可以创建两个类User和UserDetail类
  • 然后再创建一个UserVo类,其中包含User的属性和一个UserDatail对象
  1. public class User {
  2. private Integer id;
  3. private String name;
  4. private Integer age;
  5. }
  6. public class UserDetail {
  7. private Integer detailId;
  8. private String address;
  9. private String phone;
  10. }
  11. public class UserVo {
  12. private Integer id;
  13. private String name;
  14. private Integer age;
  15. private UserDetail userDetail; // 一对一关系:一个用户对应一份详细信息
  16. }

XML配置如下:

  1. <resultMap id="userVoMap" type="com.example.UserVo">
  2. <id property="id" column="id"/>
  3. <result property="name" column="name"/>
  4. <result property="age" column="age"/>
  5. <!-- 一对一映射 -->
  6. <association property="userDetail" javaType="com.example.UserDetail">
  7. <id property="detailId" column="detail_id"/>
  8. <result property="address" column="address"/>
  9. <result property="phone" column="phone"/>
  10. </association>
  11. </resultMap>
  12. <select id="getUserVoById" resultMap="userVoMap" parameterType="int">
  13. SELECT u.id, u.name, u.age, ud.detail_id, ud.address, ud.phone
  14. FROM user u
  15. LEFT JOIN user_detail ud ON u.id = ud.user_id
  16. WHERE u.id = #{id}
  17. </select>
  • <resultMap>标签
    • 用于定义一组映射规则,将查询的结果转换为一个指定类型的Java对象
    • 属性
      • id:为该映射指定一个唯一标识,供其在XML中引用使用,如<resultMap id="userResultMap" type="com.example.User">
      • type:指定映射结果对应的Java类型(对象的全路径)
  • <result>标签
    • 用于将数据库列映射到Java对象的属性,在<resultMap>中使用
    • 属性
      • property:Java对象中的属性名称,如<result property="userName" column="user_name"/>其表示将查询到的user_name列的值赋值给userName属性
      • cloumn:数据库查询结果中的列名,如column="user_name”表示sql查询列名为user_name的值
  • <id>标签
    • <id>类似于<result>主要用于映射主键字段
    • 属性
      • property:与<result>相同,映射到Java对象的主键属性
      • column:对应数据库中的主键列名
  • <association>标签
    • 表示一个一对一关连
    • 当查询到结果时,MyBatis会将用户的基本字段{id,name,age}直接映射到UserVo中,同时将详细信息{detail_id,address,phone}封装为一个UserDetail对象,并赋值到UserVo的userDetail对象中

一对多映射

提供用于有列表对象的查询

  • 现假设一个老师(Teacher)类和一个学生(student)类,一个老师可以对应多个学生,在Java中我们可以设计Teacher类, 使用List属性来存放老师的所有学生

    1. public class Teacher {
    2. private Integer id;
    3. private String teacherName;
    4. private Integer age;
    5. private List<Student> students; // 一对多关系:一个老师对应多个学生
    6. }
    7. public class Student {
    8. private Integer id;
    9. private String name;
    10. private Integer age;
    11. }

    XML配置如下:

    1. <resultMap id="teacherMap" type="com.example.Teacher">
    2. <id property="id" column="teacher_id"/>
    3. <result property="teacherName" column="teacher_name"/>
    4. <result property="age" column="teacher_age"/>
    5. <!-- 一对多映射 -->
    6. <collection property="students" ofType="com.example.Student">
    7. <id property="id" column="student_id"/>
    8. <result property="name" column="student_name"/>
    9. <result property="age" column="student_age"/>
    10. </collection>
    11. </resultMap>
    12. <select id="getTeacherWithStudents" resultMap="teacherMap" parameterType="int">
    13. SELECT t.id as teacher_id, t.teacher_name, t.age as teacher_age,
    14. s.id as student_id, s.name as student_name, s.age as student_age
    15. FROM teacher t
    16. LEFT JOIN student s ON t.id = s.teacher_id
    17. WHERE t.id = #{id}
    18. </select>
    • <collection>标签:用于表示一对多关系,把查询结果中的学生记录封装成一个列表,并赋值到Teacher对象中的student属性

原文链接:https://www.cnblogs.com/ihave2carryon/p/18756129

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号