在 MyBatis 以及 MyBatis - Plus 的开发过程中,注解的使用是提升开发效率和实现特定功能的关键。今天我们就来聊聊 @Options 注解,以及在 MyBatis - Plus 中它的使用场景和替代方案。
一、MyBatis 中的 @Options 注解
在 MyBatis 框架中,@Options 注解是一个非常实用的注解,它主要用于配置 mapper 接口方法的一些执行选项,像缓存、结果集处理、主键生成等方面都能用到它。
1. 新增数据时获取自增主键
在实际开发中,当我们向数据库中插入一条新数据时,常常需要立即获取这条数据的自增主键,以便进行后续的关联操作。在 MyBatis 中,借助 @Options 注解就能轻松实现这一功能。
例如,有一个用户表 user,其 id 是自增主键,对应的实体类 User 和 mapper 接口 UserMapper 如下:
// User实体类public class User {private Long id; // 自增主键private String username;private String email;// 省略getter和setter方法}// UserMapper接口public interface UserMapper {/*** 新增用户并获取自增主键*/@Insert("INSERT INTO user(username, email) VALUES(#{username}, #{email})")@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")void insertUser(User user);}
在业务层调用时,插入数据后可以直接通过 user.getId () 获取自增的主键:
@Servicepublic class UserService {@Autowiredprivate UserMapper userMapper;public Long addUser(User user) {userMapper.insertUser(user);return user.getId(); // 插入后直接获取自增主键}}
这里,@Options 注解的 useGeneratedKeys 属性设置为 true,表示开启自动生成主键功能;keyProperty 属性指定了主键值要注入到 User 对象的 id 属性中;keyColumn 属性则指定了数据库表中的主键列名,当与实体类的属性名一致时可以省略。通过这样的配置,避免了插入数据后再查询一次主键的额外操作,大大提升了性能。
2. 高频查询配置缓存
对于一些高频访问但不常变更的数据,比如网站首页的热门商品列表,我们可以通过 @Options 注解配置 MyBatis 二级缓存,从而减少数据库的访问压力。
// Product实体类(需要实现Serializable接口,因为缓存要求序列化)public class Product implements Serializable {private Long id;private String name;private BigDecimal price;// 省略getter和setter方法}// ProductMapper接口public interface ProductMapper {/*** 查询热门商品列表,启用缓存*/@Select("SELECT id, name, price FROM product WHERE is_hot = 1 ORDER BY sort DESC LIMIT 10")@Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 5000)List<Product> getHotProducts();/*** 更新商品信息后刷新缓存,避免缓存脏数据*/@Update("UPDATE product SET name = #{name}, price = #{price} WHERE id = #{id}")@Options(flushCache = Options.FlushCachePolicy.TRUE)void updateProduct(Product product);}
在上面的代码中,getHotProducts 方法通过 @Options 注解配置了 useCache = true,启用了二级缓存,这样后续的请求就可以直接从缓存中获取数据,而不用每次都访问数据库。同时,设置 flushCache = Options.FlushCachePolicy.FALSE,表示查询后不刷新缓存。而 updateProduct 方法设置 flushCache = Options.FlushCachePolicy.TRUE,意味着更新操作后会刷新缓存,避免了缓存中出现脏数据。
3. 大数据量查询优化
当处理大数据量查询,比如导出订单报表时,一次性加载过多数据可能会导致内存溢出。这时,我们可以使用 @Options 注解的 fetchSize 属性来控制 JDBC 每次从数据库读取的行数,进行分批读取,降低内存占用。
// OrderMapper接口public interface OrderMapper {/*** 批量查询订单,用于报表导出*/@Select("SELECT id, order_no, amount, create_time FROM `order` WHERE create_time BETWEEN #{startTime} AND #{endTime}")@Options(fetchSize = 1000, resultSetType = ResultSetType.FORWARD_ONLY)List<Order> queryOrdersByTimeRange(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);}
这里,fetchSize = 1000 表示每次从数据库读取 1000 行数据,resultSetType = ResultSetType.FORWARD_ONLY 设置结果集为只向前滚动,配合 fetchSize 可以达到分批读取数据的效果,有效优化了大数据量查询时的内存占用。
二、MyBatis - Plus 中的情况
MyBatis - Plus 是在 MyBatis 基础上的增强工具,它对很多常见功能进行了更简洁的封装,在很多场景下不需要显式使用 @Options 注解。
1. 主键生成
MyBatis - Plus 提供了 @TableId 注解专门用于主键配置,支持多种主键策略,完全可以替代 @Options 注解在主键生成方面的功能。
例如,对于自增主键,我们可以这样配置:
// 实体类public class User {// 配置主键自增,等价于MyBatis中@Options(useGeneratedKeys = true, keyProperty = "id")@TableId(type = IdType.AUTO)private Long id;private String username;// 省略其他字段和getter、setter方法}// Mapper接口(直接继承BaseMapper,无需编写SQL语句)public interface UserMapper extends BaseMapper<User> {// 插入后可以直接通过user.getId()获取自增主键}// 调用方式User user = new User();user.setUsername("testUser");userMapper.insert(user);Long id = user.getId(); // 直接获取自增主键
MyBatis - Plus 的 IdType.AUTO 会自动处理插入后返回主键的逻辑,非常方便。而且,它还支持其他主键策略,如 UUID、雪花算法等,当使用这些策略时,甚至不需要数据库设置自增,更加灵活。
2. 缓存控制
MyBatis - Plus 并没有改变 MyBatis 的缓存机制,所以如果我们使用 MyBatis 原生的二级缓存,@Options 注解仍然有效。不过,MyBatis - Plus 推荐使用 @CacheNamespace 注解在 Mapper 接口上统一配置缓存,这种方式比在每个方法上分散使用 @Options 注解更简洁。
// 使用@CacheNamespace统一配置缓存(推荐)@CacheNamespace(implementation = MybatisRedisCache.class, eviction = LruCache.class, flushInterval = 60000)public interface ProductMapper extends BaseMapper<Product> {// 所有方法默认使用缓存,无需在每个方法上添加@Options注解}// 个别方法需要特殊配置时,仍可以使用@Options注解覆盖默认配置@Select("SELECT * FROM product WHERE id = #{id}")@Options(useCache = false) // 该方法不使用缓存Product getProductById(Long id);
3. 其他参数配置
对于 fetchSize、timeout 等参数,MyBatis - Plus 没有进行额外的封装,所以在需要这些配置时,仍然需要使用 @Options 注解。
public interface OrderMapper extends BaseMapper<Order> {// 自定义批量查询SQL,设置fetchSize和timeout优化性能@Select("SELECT * FROM `order` WHERE status = #{status}")@Options(fetchSize = 1000, timeout = 10000)List<Order> selectByStatus(@Param("status") Integer status);}
三、总结
@Options 注解在 MyBatis 中有着重要的作用,能帮助我们实现主键获取、缓存控制、大数据量查询优化等功能。而在 MyBatis - Plus 中,由于其对常见功能进行了封装,在主键生成方面,我们可以使用 @TableId 注解替代 @Options;在缓存控制方面,推荐使用 @CacheNamespace 注解进行统一配置;但对于 fetchSize、timeout 等参数,仍然需要使用 @Options 注解来配置。
了解这些知识点,能让我们在使用 MyBatis 和 MyBatis - Plus 进行开发时,更加灵活地处理各种业务场景,提高开发效率和系统性能。