今日学习之JavaWeb:SpringBoot整合MyBatis

在微服务架构大行其道的今天,SpringBoot+MyBatis组合已成为Java开发者最趁手的数据库操作利器。本文从零开始,总结我对Mybits的学习

一、为什么选择MyBatis?

2023年StackOverflow调查显示,MyBatis在Java持久层框架中占有率高达42%,其核心优势在于:

  1. SQL可见性:直观看到每句SQL,便于优化

  2. 灵活映射:ResultMap实现复杂对象映射

  3. 动态SQL:XML标签实现条件动态拼接

  4. 轻量级:学习曲线平缓,与SpringBoot完美契合

二、手把手教学:从Hello World到生产级配置

2.1 初始化彩蛋(90%新手会踩的坑)

# 注意!SpringBoot 3.x的包名变革
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true
    # 必须显式指定驱动类!
    driver-class-name: com.mysql.cj.jdbc.Driver 

🛠️ 连接池选型指南

  • HikariCP:SpringBoot官方推荐,号称"快如闪电"

  • Druid:阿里出品,自带监控面板

  • Tomcat JDBC:传统项目过渡选择

2.2 Mapper接口的三种打开方式

方式一:注解派(极简主义)

@Mapper
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User findById(@Param("id") Long id);
}

方式二:XML派(掌控全局)

<!-- resources/mapper/UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper">
    <select id="findByName" resultType="User">
        SELECT * FROM user 
        WHERE user_name LIKE CONCAT('%',#{name},'%')
    </select>
</mapper>

方式三:混搭风(灵活王者)

@Mapper
public interface OrderMapper {
    // 简单查询用注解
    @Select("SELECT COUNT(*) FROM orders")
    int countAll();
    
    // 复杂查询用XML
    List<Order> searchComplexOrders(OrderQuery query);
}

💡 架构师说:中小型项目推荐混搭模式,核心业务用XML保证可维护性,边缘功能用注解提升开发速度。

三、动态SQL

3.1 基础连招:<where> + <if>

<select id="searchUsers" resultType="User">
    SELECT * FROM users
    <where>
        <if test="name != null">
            AND name LIKE #{name}
        </if>
        <if test="status != null">
            AND status = #{status}
        </if>
    </where>
    ORDER BY create_time DESC
</select>

🛡️ 防御式编程:永远使用<where>标签代替原生WHERE,避免出现WHERE AND这样的语法炸弹。

3.2 进阶奥义:<choose>的智慧

<select id="findProducts" resultType="Product">
    SELECT * FROM products
    <where>
        <choose>
            <when test="categoryIds != null">
                category_id IN 
                <foreach item="id" collection="categoryIds" 
                         open="(" separator="," close=")">
                    #{id}
                </foreach>
            </when>
            <when test="keyword != null">
                AND (name LIKE #{keyword} OR description LIKE #{keyword})
            </when>
            <otherwise>
                AND is_hot = 1
            </otherwise>
        </choose>
    </where>
</select>

🎯 业务场景:电商商品搜索页的多条件筛选,不同用户群体呈现不同默认排序。

四、开发者必备的救命锦囊

4.1 SQL调试三件套

  1. P6spy:在控制台打印真实SQL

spring:
  datasource:
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    url: jdbc:p6spy:mysql://localhost:3306/mydb

MyBatis参数美化

<configuration>
  <settings>
    <setting name="logPrefix" value="🐞 MYBATIS DEBUG => "/>
  </settings>
</configuration>

4.2 分页查询的优雅实现

PageHelper插件(快速上手)

PageHelper.startPage(1, 10);
List<User> users = userMapper.selectAll();
PageInfo<User> pageInfo = new PageInfo<>(users);

五、从代码到部署:完整链路实践

5.1 多环境配置策略

# application-dev.yml
mybatis:
  mapper-locations: classpath:mapper/**/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

# application-prod.yml  
mybatis:
  configuration:
    cache-enabled: true
    lazy-loading-enabled: true

5.2 数据库迁移方案

Flyway配置示例

-- V1__init_schema.sql
CREATE TABLE user (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    user_name VARCHAR(255) NOT NULL
);

-- V2__add_index.sql
CREATE INDEX idx_user_name ON user(user_name);
<dependency>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-core</artifactId>
</dependency>

六、前方高能:常见天坑预警

6.1 事务失效的N种死法

错误案例

@Service
public class UserService {
    // 错误!直接调用同类方法不会走代理
    public void createUser(User user) {
        insertUser(user);
        insertLog(user); // 第二个插入失败不会回滚
    }
    
    @Transactional
    public void insertUser(User user) { ... }
    
    @Transactional
    public void insertLog(User user) { ... }
}

正确姿势

@Service
public class UserService {
    @Transactional
    public void createUser(User user) {
        userMapper.insert(user);
        logService.insertLog(user); // 通过代理对象调用
    }
}

6.2 类型处理器的暗雷

问题场景
MySQL的TINYINT(1)被MyBatis默认映射为Boolean,导致存2时报错

解决方案

@MappedJdbcTypes(JdbcType.TINYINT)
@MappedTypes(Integer.class)
public class CustomBooleanTypeHandler extends BaseTypeHandler<Integer> {
    // 实现类型转换逻辑
}

避坑指南(血泪经验)

  1. 事务管理:在Service层添加@Transactional

  2. 参数传递:多个参数必须使用@Param注解

  3. Lombok兼容:Entity类需要添加@NoArgsConstructor

  4. SQL注入防护:禁止使用${}进行字符串拼接

结语

SpringBoot与MyBatis的整合,就像咖啡遇上奶泡般完美。掌握本文技巧后,你将能:

✅ 快速搭建企业级数据访问层
✅ 轻松应对复杂查询场景
✅ 写出高性能的数据库操作代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值