当前位置: 首页 > news >正文

【Java EE】MyBatis 全面详解

目录

一、MyBatis 架构与核心概念

1.1 MyBatis 整体架构

​编辑1.2 核心组件说明

二、环境配置与设置

2.1 Maven依赖配置

2.2 配置文件详解

三、实体类与表映射

3.1 实体类设计

3.2 数据库表结构

四、Mapper接口与SQL映射

4.1 注解方式

4.2 XML映射方式

五、动态SQL详解

5.1 常用动态SQL元素

六、高级特性与性能优化

6.1 缓存机制

6.2 分页插件

6.3 类型处理器

七、事务管理

7.1 声明式事务

7.2 编程式事务

八、最佳实践与常见问题

8.1 SQL注入防护

8.2 性能优化建议

8.3 常见问题解决方案


一、MyBatis 架构与核心概念

1.1 MyBatis 整体架构

MyBatis 是一个优秀的持久层框架,它封装了JDBC操作,简化了数据库交互流程。下面是MyBatis的核心架构图:

1.2 核心组件说明

  • SqlSessionFactoryBuilder​:用于创建SqlSessionFactory实例

  • SqlSessionFactory​:工厂模式,创建SqlSession实例

  • SqlSession​:核心接口,提供CRUD操作API

  • Executor​:SQL执行器,负责语句缓存、结果处理

  • Mapped Statements​:存储SQL映射信息(注解或XML)

二、环境配置与设置

2.1 Maven依赖配置

<!-- MyBatis Spring Boot Starter -->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version>
</dependency><!-- MySQL驱动 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version>
</dependency><!-- 连接池 -->
<dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId>
</dependency>

2.2 配置文件详解

application.yml 配置:​

spring:datasource:url: jdbc:mysql://localhost:3306/mybatis_demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driverhikari:pool-name: MyBatis-HikariCPmaximum-pool-size: 20minimum-idle: 5idle-timeout: 30000connection-timeout: 30000max-lifetime: 1800000mybatis:configuration:map-underscore-to-camel-case: true  # 开启驼峰命名自动映射cache-enabled: true                 # 开启缓存lazy-loading-enabled: true          # 开启延迟加载aggressive-lazy-loading: false      # 按需加载log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # 日志实现mapper-locations: classpath:mapper/**/*.xml  # XML映射文件位置type-aliases-package: com.example.model     # 实体类别名包

三、实体类与表映射

3.1 实体类设计

package com.example.model;import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;@Data
public class User {private Long id;private String userName;      // 映射到 user_nameprivate String email;private Integer age;private Integer status;private LocalDateTime createTime;private LocalDateTime updateTime;// 一对一关系private UserProfile profile;// 一对多关系private List<Order> orders;
}@Data
public class UserProfile {private Long id;private Long userId;private String realName;private String idCard;private String address;
}@Data
public class Order {private Long id;private Long userId;private String orderNo;private BigDecimal amount;private Integer status;private LocalDateTime createTime;
}

3.2 数据库表结构

-- 用户表
CREATE TABLE `user` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`user_name` varchar(50) NOT NULL COMMENT '用户名',`email` varchar(100) NOT NULL COMMENT '邮箱',`age` int(11) DEFAULT NULL COMMENT '年龄',`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态:1-正常,0-禁用',`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 `uk_user_name` (`user_name`),UNIQUE KEY `uk_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';-- 用户信息表
CREATE TABLE `user_profile` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`user_id` bigint(20) NOT NULL COMMENT '用户ID',`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',`id_card` varchar(18) DEFAULT NULL COMMENT '身份证号',`address` varchar(200) DEFAULT NULL COMMENT '地址',PRIMARY KEY (`id`),UNIQUE KEY `uk_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';-- 订单表
CREATE TABLE `order` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`user_id` bigint(20) NOT NULL COMMENT '用户ID',`order_no` varchar(20) NOT NULL COMMENT '订单号',`amount` decimal(10,2) NOT NULL COMMENT '订单金额',`status` tinyint(4) NOT NULL COMMENT '订单状态',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`),KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

四、Mapper接口与SQL映射

4.1 注解方式

package com.example.mapper;import com.example.model.User;
import org.apache.ibatis.annotations.*;import java.util.List;
import java.util.Map;@Mapper
public interface UserMapper {// 基本查询@Select("SELECT * FROM user WHERE id = #{id}")User selectById(Long id);// 结果映射@Results({@Result(property = "id", column = "id"),@Result(property = "userName", column = "user_name"),@Result(property = "createTime", column = "create_time"),@Result(property = "updateTime", column = "update_time")})@Select("SELECT * FROM user WHERE user_name = #{userName}")User selectByUserName(String userName);// 插入并返回主键@Options(useGeneratedKeys = true, keyProperty = "id")@Insert("INSERT INTO user(user_name, email, age) VALUES(#{userName}, #{email}, #{age})")int insert(User user);// 批量插入@Insert("<script>" +"INSERT INTO user(user_name, email, age) VALUES " +"<foreach collection='list' item='item' separator=','>" +"(#{item.userName}, #{item.email}, #{item.age})" +"</foreach>" +"</script>")int insertBatch(List<User> users);// 更新操作@Update("UPDATE user SET email = #{email}, age = #{age} WHERE id = #{id}")int update(User user);// 条件更新@Update("<script>" +"UPDATE user " +"<set>" +"  <if test='userName != null'>user_name = #{userName},</if>" +"  <if test='email != null'>email = #{email},</if>" +"  <if test='age != null'>age = #{age},</if>" +"</set>" +"WHERE id = #{id}" +"</script>")int updateSelective(User user);// 删除操作@Delete("DELETE FROM user WHERE id = #{id}")int delete(Long id);// 复杂查询@Select("<script>" +"SELECT * FROM user " +"<where>" +"  <if test='userName != null'>AND user_name LIKE CONCAT('%', #{userName}, '%')</if>" +"  <if test='email != null'>AND email = #{email}</if>" +"  <if test='minAge != null'>AND age &gt;= #{minAge}</if>" +"  <if test='maxAge != null'>AND age &lt;= #{maxAge}</if>" +"  <if test='status != null'>AND status = #{status}</if>" +"</where>" +"ORDER BY ${orderBy} ${sortDirection}" +"</script>")List<User> selectByCondition(Map<String, Object> params);
}

4.2 XML映射方式

UserMapper.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.example.mapper.UserMapper"><!-- 基础结果映射 --><resultMap id="BaseResultMap" type="User"><id column="id" property="id"/><result column="user_name" property="userName"/><result column="email" property="email"/><result column="age" property="age"/><result column="status" property="status"/><result column="create_time" property="createTime"/><result column="update_time" property="updateTime"/></resultMap><!-- 关联映射 - 一对一 --><resultMap id="UserWithProfileResultMap" type="User" extends="BaseResultMap"><association property="profile" javaType="UserProfile"><id column="profile_id" property="id"/><result column="user_id" property="userId"/><result column="real_name" property="realName"/><result column="id_card" property="idCard"/><result column="address" property="address"/></association></resultMap><!-- 关联映射 - 一对多 --><resultMap id="UserWithOrdersResultMap" type="User" extends="BaseResultMap"><collection property="orders" ofType="Order"><id column="order_id" property="id"/><result column="user_id" property="userId"/><result column="order_no" property="orderNo"/><result column="amount" property="amount"/><result column="order_status" property="status"/><result column="order_create_time" property="createTime"/></collection></resultMap><!-- 查询用户及其详情 --><select id="selectUserWithProfile" resultMap="UserWithProfileResultMap">SELECT u.*, up.id as profile_id, up.user_id, up.real_name, up.id_card, up.addressFROM user uLEFT JOIN user_profile up ON u.id = up.user_idWHERE u.id = #{id}</select><!-- 查询用户及其订单 --><select id="selectUserWithOrders" resultMap="UserWithOrdersResultMap">SELECT u.*, o.id as order_id, o.user_id, o.order_no, o.amount, o.status as order_status, o.create_time as order_create_timeFROM user uLEFT JOIN order o ON u.id = o.user_idWHERE u.id = #{id}</select><!-- 动态SQL查询 --><select id="selectByDynamicCondition" resultMap="BaseResultMap">SELECT * FROM user<where><if test="userName != null and userName != ''">AND user_name LIKE CONCAT('%', #{userName}, '%')</if><if test="email != null and email != ''">AND email = #{email}</if><if test="minAge != null">AND age >= #{minAge}</if><if test="maxAge != null">AND age <= #{maxAge}</if><if test="status != null">AND status = #{status}</if><if test="createTimeStart != null">AND create_time >= #{createTimeStart}</if><if test="createTimeEnd != null">AND create_time <= #{createTimeEnd}</if></where><choose><when test="orderBy != null and orderBy != ''">ORDER BY ${orderBy}<if test="sortDirection != null and sortDirection != ''">${sortDirection}</if></when><otherwise>ORDER BY id DESC</otherwise></choose><if test="limit != null">LIMIT #{limit}</if><if test="offset != null">OFFSET #{offset}</if></select><!-- 批量插入 --><insert id="insertBatch" parameterType="java.util.List">INSERT INTO user(user_name, email, age, status)VALUES<foreach collection="list" item="item" separator=",">(#{item.userName}, #{item.email}, #{item.age}, #{item.status})</foreach></insert><!-- 批量更新 --><update id="updateBatch" parameterType="java.util.List"><foreach collection="list" item="item" separator=";">UPDATE user<set><if test="item.userName != null">user_name = #{item.userName},</if><if test="item.email != null">email = #{item.email},</if><if test="item.age != null">age = #{item.age},</if><if test="item.status != null">status = #{item.status}</if></set>WHERE id = #{item.id}</foreach></update>
</mapper>

五、动态SQL详解

MyBatis提供了强大的动态SQL功能,可以根据条件动态构建SQL语句。

5.1 常用动态SQL元素

<!-- if元素 -->
<select id="findUsers" resultMap="BaseResultMap">SELECT * FROM user<where><if test="userName != null">AND user_name = #{userName}</if><if test="email != null">AND email = #{email}</if></where>
</select><!-- choose, when, otherwise -->
<select id="findActiveUsers" resultMap="BaseResultMap">SELECT * FROM user<where><choose><when test="userName != null">AND user_name = #{userName}</when><when test="email != null">AND email = #{email}</when><otherwise>AND status = 1</otherwise></choose></where>
</select><!-- foreach元素 -->
<select id="findUsersByIds" resultMap="BaseResultMap">SELECT * FROM userWHERE id IN<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
</select><!-- set元素(用于更新) -->
<update id="updateUser">UPDATE user<set><if test="userName != null">user_name = #{userName},</if><if test="email != null">email = #{email},</if><if test="age != null">age = #{age},</if></set>WHERE id = #{id}
</update><!-- trim元素(自定义前后缀) -->
<insert id="insertUser">INSERT INTO user<trim prefix="(" suffix=")" suffixOverrides=","><if test="userName != null">user_name,</if><if test="email != null">email,</if><if test="age != null">age,</if></trim><trim prefix="VALUES (" suffix=")" suffixOverrides=","><if test="userName != null">#{userName},</if><if test="email != null">#{email},</if><if test="age != null">#{age},</if></trim>
</insert>

六、高级特性与性能优化

6.1 缓存机制

MyBatis提供两级缓存机制,提高查询性能:

缓存配置示例:​

<!-- 开启二级缓存 -->
<cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/><!-- 使用第三方缓存(如Ehcache) -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

6.2 分页插件

使用PageHelper实现物理分页:

// Maven依赖
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</version>
</dependency>// 使用示例
public PageInfo<User> getUsersByPage(int pageNum, int pageSize, String userName) {PageHelper.startPage(pageNum, pageSize);List<User> users = userMapper.selectByUserName(userName);return new PageInfo<>(users);
}

6.3 类型处理器

自定义类型处理器处理复杂类型:

// JSON类型处理器
@MappedTypes({Map.class, List.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class JsonTypeHandler extends BaseTypeHandler<Object> {private static final ObjectMapper objectMapper = new ObjectMapper();@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, toJson(parameter));}@Overridepublic Object getNullableResult(ResultSet rs, String columnName) throws SQLException {return parse(rs.getString(columnName));}// 其他方法实现...
}

七、事务管理

7.1 声明式事务

@Service
@Transactional
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate OrderMapper orderMapper;@Override@Transactional(rollbackFor = Exception.class)public void createUserWithOrder(User user, Order order) {// 插入用户userMapper.insert(user);// 设置订单的用户IDorder.setUserId(user.getId());// 插入订单orderMapper.insert(order);// 如果此处抛出异常,两个操作都会回滚}
}

7.2 编程式事务

@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate PlatformTransactionManager transactionManager;@Overridepublic void updateWithTransaction(User user) {TransactionDefinition definition = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(definition);try {userMapper.update(user);// 其他数据库操作...transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);throw e;}}
}

八、最佳实践与常见问题

8.1 SQL注入防护

// 错误示例:存在SQL注入风险
@Select("SELECT * FROM user WHERE user_name = '${userName}'")
User findByUserNameInsecure(@Param("userName") String userName);// 正确示例:使用#{}预编译
@Select("SELECT * FROM user WHERE user_name = #{userName}")
User findByUserNameSecure(@Param("userName") String userName);// 动态排序字段安全处理
public List<User> findUsers(String orderBy) {// 校验orderBy参数是否合法if (!isValidOrderByField(orderBy)) {orderBy = "id";}return userMapper.selectUsersWithOrder(orderBy);
}

8.2 性能优化建议

  1. 批量操作​:使用批量插入和更新减少数据库交互

  2. 分页查询​:大数据集使用分页,避免一次性加载过多数据

  3. 延迟加载​:关联数据使用延迟加载,按需获取

  4. 索引优化​:为查询条件字段添加合适索引

  5. SQL优化​:避免SELECT *,只查询需要的字段

8.3 常见问题解决方案

问题1:实体类属性与表字段不一致

解决方案:使用resultMap映射或开启驼峰命名

问题2:循环引用导致序列化失败

解决方案:使用@JsonIgnore注解或DTO对象

问题3:大数据量查询内存溢出

解决方案:使用分页或游标查询

问题4:事务不生效

解决方案:检查@Transactional配置,确保代理生效

http://www.dtcms.com/a/435387.html

相关文章:

  • 南宁网站 制作wordpress怎么登陆ftp
  • JSON 与 Form Data 在接口测试中的技术对比与应用指南
  • 网站建设制作微商授权书个人博客网站设计的目的
  • 51c自动驾驶~合集36
  • 天猫魔盒M19技凡科技定制版OS刷机教程
  • 临沧网站建设安徽智能网站建设
  • 【MySQL初阶】05-CRUD-Create
  • 2017 年真题配套词汇单词笔记(考研真相)
  • 网站建设app开发网上装修公司网站策划书
  • 【开题答辩全过程】以 springboot类站酷设计师为例,包含答辩的问题和答案
  • 做网站社区赚钱吗wordpress 收邮件
  • 温州苍南网站建设大型免费网站制作
  • Spring Boot 热部署配置与禁用
  • 专门建立网站的公司吗青岛物流网站建设
  • 网站开发网站设计素材p2p理财网站开发
  • 什么是域名 空间 网站源代码韩国女足出线
  • 给客户做网站建设方案wordpress中文变英文
  • 江西省建设工程造价管理局网站使用wordpress的网站
  • Java Web综合项目实战 - 西蒙购物网
  • Photoshop - Photoshop 更改图像大小
  • 整理k8s中Pod、Deployment和Service的spec配置项--图文篇
  • 网站备案以后怎么做网站建设属于销售费用
  • [QT]常用控件一
  • 探究Function Calling 和 MCP 的奥秘
  • 网站如何做前后端分离网络营销课程学什么
  • 自己手机怎么免费做网站安徽四建东方建设有限公司网站
  • 域名后缀cn做网站家装设计师需要考证吗
  • 广州网站vi设计报价网站建设 图片问题
  • 数据安全能力成熟度模型 (DSMM) 核心要点
  • 飞算JavaAI 使用指南