MyBatis 实战案例:从 0 到 1 搭建企业级持久层
一、前言:为什么选择 MyBatis?
在企业级应用开发中,持久层是至关重大的一环。MyBatis 在 SQL 可控性 与 开发效率 之间取得了平衡:
- 相比全自动 ORM(如 Hibernate),它让开发者能编写和优化原生 SQL。
- 相比传统 JDBC,它大幅减少了样板代码。
因此,MyBatis 在电商、金融、政企系统中被广泛使用。本文将带你从零开始搭建一个 基于 Spring Boot + MyBatis 的持久层,并逐步覆盖 初级 → 中级 → 高级 → 企业级实战 场景。
二、项目搭建与环境配置
1. Maven 依赖
推荐使用 Spring Boot + MyBatis Starter 简化配置:
<dependencies>
<!-- Web 层 (可选,如需提供 REST 接口) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JDBC & 数据源支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MyBatis 集成 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version>
</dependency>
<!-- 开发工具,支持热加载 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2. application.yml 配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis_demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.model
configuration:
map-underscore-to-camel-case: true
cache-enabled: true
default-executor-type: reuse
logging:
level:
com.example.mapper: debug
3. 表结构与实体类
CREATE TABLE `user` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',
`email` VARCHAR(100) NOT NULL COMMENT '邮箱',
`status` TINYINT DEFAULT 1 COMMENT '状态:0-禁用,1-启用',
`version` INT DEFAULT 0 COMMENT '乐观锁版本号',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_username (username),
INDEX idx_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
public class User {
private Long id;
private String username;
private String email;
private Integer status;
private Integer version;
private LocalDateTime createTime;
private LocalDateTime updateTime;
// getter、setter省略
}
三、基础 CRUD 操作(初级)
1. Mapper 接口
@Mapper
public interface UserMapper {
User getUserById(Long id);
User getUserByUsername(String username);
List<User> getAllUsers();
int insertUser(User user);
int updateUser(User user);
int updateEmailById(@Param("id") Long id, @Param("email") String email);
int deleteUserById(Long id);
}
2. Mapper XML
<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="userMap" type="User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="email" column="email"/>
<result property="status" column="status"/>
<result property="version" column="version"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<select id="getUserById" resultMap="userMap">
SELECT * FROM user WHERE id = #{id}
</select>
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user(username, email, status)
VALUES(#{username}, #{email}, #{status})
</insert>
<update id="updateUser">
UPDATE user
SET email = #{email}, status = #{status}, version = version + 1
WHERE id = #{id} AND version = #{version}
</update>
<delete id="deleteUserById">
DELETE FROM user WHERE id = #{id}
</delete>
</mapper>
3. Service 层
@Service
@Transactional
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUserById(Long id) {
return userMapper.getUserById(id);
}
public void addUser(User user) {
if (userMapper.getUserByUsername(user.getUsername()) != null) {
throw new RuntimeException("用户名已存在");
}
userMapper.insertUser(user);
}
public boolean updateUser(User user) {
return userMapper.updateUser(user) > 0;
}
}
四、进阶功能(中级)
1. 动态 SQL
<select id="findUsers" resultMap="userMap">
SELECT * FROM user
<where>
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="email != null and email != ''">
AND email LIKE CONCAT('%', #{email}, '%')
</if>
<if test="status != null">
AND status = #{status}
</if>
</where>
ORDER BY id DESC
</select>
2. 批量操作
<insert id="batchInsertUsers">
INSERT INTO user(username, email, status) VALUES
<foreach collection="list" item="user" separator=",">
(#{user.username}, #{user.email}, #{user.status})
</foreach>
</insert>
3. 分页查询(PageHelper)
PageHelper.startPage(1, 10);
List<User> users = userMapper.findUsers("tom", 1);
PageInfo<User> pageInfo = new PageInfo<>(users);
五、高级特性(企业级)
1. 自定义 TypeHandler
@MappedTypes(UserStatus.class)
@MappedJdbcTypes(JdbcType.INTEGER)
public class UserStatusTypeHandler extends BaseTypeHandler<UserStatus> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, UserStatus parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getCode());
}
@Override
public UserStatus getNullableResult(ResultSet rs, String columnName) throws SQLException {
return UserStatus.fromCode(rs.getInt(columnName));
}
}
2. 乐观锁
<update id="updateUser">
UPDATE user
SET email = #{email}, version = version + 1
WHERE id = #{id} AND version = #{version}
</update>
3. 二级缓存
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
<property name="timeToLiveSeconds" value="3600"/>
<property name="maxEntriesLocalHeap" value="1000"/>
</cache>
六、最佳实践与常见陷阱
- 避免 SQL 注入:使用 #{} 而不是 ${}。
- 避免 N+1 查询:合理使用 <association>、<collection>。
- 大数据处理:使用分页或流式查询。
- 批量优化:使用 ExecutorType.BATCH。
- 事务回滚:@Transactional(rollbackFor = Exception.class)。
七、项目结构示例
src/main/java/com/example
├── controller
│ └── UserController.java
├── service
│ └── UserService.java
├── mapper
│ └── UserMapper.java
├── model
│ └── User.java
├── handler
│ └── UserStatusTypeHandler.java
└── Application.java
src/main/resources
├── mapper
│ └── UserMapper.xml
└── application.yml
八、总结与扩展
通过本文你已经掌握了:
- 初级:CRUD、配置
- 中级:动态 SQL、分页、批量操作
- 高级:TypeHandler、乐观锁、二级缓存
- 企业级实战:事务管理、性能优化、最佳实践
扩展方向:
- 使用 MyBatis-Plus 简化 CRUD。
- 配置 多数据源 与 分库分表(结合 ShardingSphere)。
- 开发 自定义插件 拦截 SQL。
- 在 微服务架构 下整合 MyBatis 与分布式事务。
© 版权声明
文章版权归作者所有,未经允许请勿转载。



是是是