【MyBatis】@Results注解的使用
Results@Results在 MyBatis 中,@Results注解用于将数据库的字段和 Java 实体类的属性进行映射,特别是在的情况下。MyBatis 默认会使用,但如果数据库字段使用 snake_case(下划线命名法),而 Java 类使用camelCase(驼峰命名法),就可能需要手动指定映射关系。这时可以使用@Results注解。(或者也可以在配置文件中设置@Results假设t
@Results 注解详解
在 MyBatis 中,@Results 注解用于将数据库的字段和 Java 实体类的属性进行映射,特别是在 字段名与属性名不一致 的情况下。
MyBatis 默认会使用 自动映射,但如果数据库字段使用 snake_case(下划线命名法),而 Java 类使用 camelCase(驼峰命名法),就可能需要手动指定映射关系。这时可以使用 @Results 注解。(或者也可以在配置文件中设置<setting name="mapUnderscoreToCamelCase" value="true"/>)
1. @Results 的基本用法
示例:基本映射
假设 t_user 表的字段如下:
| id | user_name | user_email |
|---|---|---|
| 1 | Alice | alice@example.com |
| 2 | Bob | bob@example.com |
对应的 User 实体类:
public class User {
private Integer id;
private String userName; // 和数据库的 user_name 字段不匹配
private String email; // 和数据库的 user_email 不匹配
// getter & setter 略
}
UserMapper 接口:
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {
@Select("SELECT id, user_name, user_email FROM t_user")
@Results({
@Result(property = "userName", column = "user_name"),
@Result(property = "email", column = "user_email")
})
List<User> selectUsers();
}
解释
@Results({ ... }):定义字段与属性的映射@Result(property = "userName", column = "user_name"):将数据库的user_name字段映射到userName属性@Result(property = "email", column = "user_email"):将数据库的user_email字段映射到email属性
这样,查询结果中的 user_name 和 user_email 就能正确映射到 User 类的 userName 和 email 变量。
2. @Result 的常用参数
@Result(
property = "实体类属性名", // Java 实体类中的属性
column = "数据库字段名", // 数据库表的字段名
id = true/false, // 是否为主键
javaType = Java类型.class, // 指定 Java 类型
jdbcType = JdbcType.VARCHAR, // 指定 JDBC 类型
typeHandler = 自定义TypeHandler.class, // 自定义类型转换器
one = @One(select = "方法路径"), // 一对一映射,和 <association> 类似
many = @Many(select = "方法路径") // 一对多映射,和 <collection> 类似
)
3. id = true(标识主键)
如果某个字段是 主键,需要使用 id = true 来标识:
@Results({
@Result(property = "id", column = "id", id = true),
@Result(property = "userName", column = "user_name"),
@Result(property = "email", column = "user_email")
})
4. @Result 指定 javaType 和 jdbcType
如果数据库的字段类型和 Java 类型不匹配,可以在@Result 注解中显式指定 javaType 和 jdbcType:
例子:
假设我们有一个数据库表 tab_user,其字段类型与 Java 类型不完全匹配,且需要明确指定转换规则。比如,tab_user 表中的 birth_date 字段是 VARCHAR 类(存储日期字符串),但想将其映射为 Date 类。
数据库表 tab_user :
| id | username | age | birth_date |
|---|---|---|---|
| 1 | Alice | 25 | 1996-05-15 |
| 2 | Bob | 30 | 1991-08-22 |
注意:MyBatis 会使用内置的类型处理器,自动将符合yyyy-MM-dd格式的
VARCHAR日期字符串转换为Date类型,所以这里我们不用自己写,只需指定 javaType 和 jdbcType。
对应的 Java 实体类 User:
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
public class User {
private Integer id;
private String username;
private Integer age;
private Date birthDate; // 对应 VARCHAR 类型(日期字符串)
}
UserMapper 接口:
package org.example.mb_study.mapper;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.type.JdbcType;
import org.example.mb_study.entity.User;
import java.util.Date;
import java.util.List;
public interface UserMapper {
@Select("SELECT id, username, age, birth_date FROM tab_user")
@Results({
@Result(property = "birthDate", column = "birth_date", javaType = Date.class, jdbcType = JdbcType.VARCHAR)
})
List<User> selectUsers();
}
解释:
@Result(property = "birthDate", column = "birth_date", javaType = Date.class, jdbcType = JdbcType.VARCHAR):- 数据库中的
birth_date字段类型是VARCHAR(字符串),但是我们希望将它映射为 Java 中的Date类型。为了确保正确转换,我们需要指定javaType为Date.class和jdbcType为JdbcType.VARCHAR。
- 数据库中的
为什么需要显式指定 javaType 和 jdbcType?
jdbcType:当数据库中字段的类型和 Java 类型不一致时,比如,数据库中的日期字段可能是VARCHAR类型存储日期字符串,而不是DATE或TIMESTAMP,此时需要显式指定jdbcType = JdbcType.VARCHAR,以避免自动映射时产生错误。javaType:在一些情况下,MyBatis 会尝试自动推断 Java 类型,但有时这种推断并不准确,尤其是当数据库列的类型无法直接映射到 Java 类型时。显式指定javaType可以确保正确转换数据类型。
5. @Result + @One(一对一映射)
如果一个 User 关联了 Address,可以用 @One 进行查询:
表结构
| id | username | address_id |
|---|---|---|
| 1 | Alice | 101 |
| 2 | Bob | 102 |
| id | street |
|---|---|
| 101 | 123 Main St |
| 102 | 456 Oak Ave |
实体类
public class Address {
private Integer id;
private String street;
// getter & setter
}
public class User {
private Integer id;
private String userName;
private Address address; // 一对一映射
// getter & setter
}
查询 User 时,自动查询 Address
@Select("SELECT id, username, address_id FROM t_user")
@Results({
@Result(property = "address", column = "address_id",
one = @One(select = "org.example.mapper.AddressMapper.selectById"))
})
List<User> selectUsers();
@One(select = "org.example.mapper.AddressMapper.selectById"):address_id通过AddressMapper.selectById方法查找Address信息- 相当于
select * from t_address where id = #{address_id}
6. @Result + @Many(一对多映射)
如果 User 关联多个 Order,可以用 @Many 进行查询:
表结构
| user_id | order_id | order_name |
|---|---|---|
| 1 | 1001 | Phone |
| 1 | 1002 | Laptop |
| 2 | 1003 | Keyboard |
实体类
public class Order {
private Integer id;
private String orderName;
}
public class User {
private Integer id;
private String userName;
private List<Order> orders; // 一对多映射:一个用户对应多个订单
}
查询 User 时,自动查询 Order
@Select("SELECT id, username FROM t_user")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "userName", column = "username"),
@Result(property = "orders", column = "id",
many = @Many(select = "org.example.mapper.OrderMapper.selectByUserId"))
})
List<User> selectUsers();
@Many(select = "org.example.mapper.OrderMapper.selectByUserId"):orders通过OrderMapper.selectByUserId查找订单列表- 相当于
select * from t_order where user_id = #{id}
总结
| 功能 | 关键用法 |
|---|---|
| 字段映射 | @Result(property, column) |
| 标识主键 | id = true |
| 指定 Java 类型 | javaType = Integer.class |
| 指定 JDBC 类型 | jdbcType = JdbcType.INTEGER |
| 一对一查询 | one = @One(select = "...") |
| 一对多查询 | many = @Many(select = "...") |
@Results 在 字段名与属性名不一致 或 查询需要复杂映射 时非常有用。如果查询结构复杂,建议使用 resultMap 进行映射。
相关链接:
@Many
@One
@Results与<resultMap>的比较
注:作者在撰写过程中适度使用 AI 工具进行语言表达与结构组织的辅助。文中所有思想、论证与结论均经过作者的独立思考、审核与修订,AI 不参与内容决策,也不替代作者的专业判断。
更多推荐

所有评论(0)