Select
1. id
作用:这条 SQL 的“身份证号”,在同一个房间里(命名空间内)必须唯一。
例子:就像你去银行办业务,每个窗口都有一个编号(比如“3号窗口”),你告诉工作人员“我要去3号窗口”,他们就知道该找谁。
2. parameterType
作用:告诉 MyBatis 这条 SQL 要用的参数是什么类型(比如一个 User
对象)。
例子:你点奶茶时说“我要一杯大杯的”,店员就知道用大杯装。但如果你不说,店员也能从你的手势猜出来(MyBatis 会自己猜类型)。
3. parameterMap(已废弃)
作用:以前用来描述参数怎么和 SQL 对应,但现在大家都直接用“#{属性名}”写在 SQL 里,更方便。
例子:就像以前写信要贴邮票,现在直接用微信扫码支付,没人再用邮票了。
4. resultType
作用:告诉 MyBatis 这条 SQL 返回的数据要转成什么类型(比如 User
对象)。
细节:如果返回的是一个列表(比如 List<User>
),这里填的是 User
,不是 List
。
例子:你网购一箱苹果,快递单上写的是“苹果”(单个类型),而不是“一箱苹果”。
5. resultMap
作用:如果结果很复杂(比如数据要拆成多个对象),用这个指向一个提前写好的“映射说明书”。
例子:就像组装乐高时,说明书会告诉你哪块积木放哪里,而不是让你自己瞎猜。
6. flushCache
作用:设为 true
时,执行这条 SQL 后会清空缓存(下次查询重新查数据库)。
默认:false
(不清空)。
场景:适合增删改操作,比如你删了商品,下次查询不想看到缓存里的旧数据。
7. useCache
作用:设为 true
时,这条 SQL 的结果会被缓存(下次同样查询直接拿缓存)。
默认:对查询语句(select)是 true
,其他语句(如 insert)无效。
场景:比如你查天气,一天内同样的查询直接用缓存,不用每次都问气象局。
8. timeout
作用:设置数据库执行的超时时间(比如 10 秒没结果就报错)。
默认:数据库自己决定。
例子:就像你打电话客服,等了 5 分钟还没人接,你直接挂断。
9. fetchSize
作用:建议数据库一次批量返回多少条数据(比如一次拿 100 条)。
例子:快递小哥送快递,一次搬一箱(100 件)比一件件拿更快。
10. statementType
作用:选择执行 SQL 的工具,默认用预编译(防 SQL 注入)。
选项:
STATEMENT
:直接执行(像手写纸条)。PREPARED
(默认):预编译(像用模板盖章)。CALLABLE
:调用存储过程(像打电话让后台处理)。
11. resultSetType
作用:控制结果集的遍历方式(比如只能向前翻,或自由滚动)。
默认:数据库驱动决定。
例子:看书时,有的书只能一页页翻,有的可以随便翻到任意页。
12. databaseId
作用:根据数据库类型(比如 MySQL 或 Oracle)选择执行不同的 SQL。
例子:同样一道菜,四川人吃辣,广东人吃清淡,厨子会根据顾客口味调整。
13. resultOrdered
作用:处理大量嵌套数据时,避免内存爆炸。设为 true
会优化内存。
默认:false
。
场景:像整理行李箱,如果衣服一件套一件,不整理的话会塞不下。
14. resultSets
作用:用于存储过程返回多个结果集时,给每个结果集起名字。
例子:像吃套餐,服务员端上来“主菜、配菜、汤”,你可以分别指定名字。
insert, update 和 delete
1. id
作用:这条 SQL 的“唯一名字”,在同一个 XML 文件里不能重复。
例子:就像微信好友列表里每个人的昵称必须唯一,否则你@人的时候会分不清谁是谁。
2. parameterType
作用:告诉 MyBatis 参数是什么类型(比如 User
类)。
细节:可省略,MyBatis 能自己猜类型。
例子:你点外卖时说“要一杯奶茶”,即使不说“大杯”,店员默认也会给你大杯(如果系统有默认值)。
3. parameterMap(已废弃)
作用:以前用来描述参数和 SQL 的映射关系,现在直接用 #{属性名}
更简单。
现状:别用它,像过时的翻盖手机,现在都用智能手机(行内参数映射)。
4. flushCache
作用:设为 true
时,执行这条 SQL 后会清空缓存(默认 insert/update/delete 会清空)。
默认值:对增删改操作是 true
(比如你删了数据,下次查肯定要重新读数据库)。
场景:你修改了密码,肯定不希望别人用旧密码的缓存登录。
5. timeout
作用:设置 SQL 执行的超时时间(比如 10 秒没结果就报错)。
默认:数据库驱动自己决定。
例子:等电梯超过 2 分钟还没来,你可能直接走楼梯(超时报错)。
6. statementType
作用:选择执行 SQL 的工具类型。
选项:
STATEMENT
:直接执行(像手写纸条传给数据库,容易被 SQL 注入攻击)。PREPARED
(默认):预编译(像用模板盖章,安全高效)。CALLABLE
:调用存储过程(像打电话让数据库后台处理)。
例子:发邮件时,用模板(PREPARED
)比每次手写(STATEMENT
)更省事。
7. useGeneratedKeys
作用:(仅 insert/update 用)告诉 MyBatis 去拿数据库自动生成的主键(比如 MySQL 的自增 ID)。
默认:false
(不拿)。
场景:你存钱到银行,柜台给你一张存单号(自增 ID),useGeneratedKeys
就是让你能拿到这个号码。
8. keyProperty
作用:(配合 useGeneratedKeys
)把生成的主键值塞到参数的哪个属性里。
例子:你存钱后拿到存单号,银行系统会自动把这个号码填到你的账户记录里(比如 user.id
)。
9. keyColumn
作用:数据库表中生成主键的列名(如果主键列不是第一列,某些数据库需要指定)。
场景:比如 PostgreSQL 的主键列可能在第二列,这时候必须告诉 MyBatis 列名。
例子:快递单号可能在快递单的第二行,你得明确告诉快递员“看第二行的编号”。
10. databaseId
作用:根据数据库类型(MySQL、Oracle 等)选择执行不同的 SQL。
例子:就像同一款 App,iOS 和 Android 的安装包不同,MyBatis 会根据当前数据库加载对应的 SQL。
总结
-
写操作(insert/update/delete)重点关注:
flushCache
(默认清缓存)useGeneratedKeys
+keyProperty
(拿自增 ID)keyColumn
(适配非常规主键列)
-
防踩坑提示:
- 别用
parameterMap
(已废弃)。 - 如果主键不是自增的,不要开
useGeneratedKeys
。 - 超时时间(
timeout
)设太短可能导致正常请求报错。
- 别用
selectKey 元素的属性
1. keyProperty
作用:告诉 MyBatis:“把生成的主键值,存到我对象的哪个属性里”。
场景:
- 单主键:比如插入用户后,数据库自动生成的
id
,要存到对象的user.id
属性。 - 多主键:如果主键是复合的(比如订单号+地区码),用逗号分隔多个属性名,比如
keyProperty="orderId, areaCode"
。
例子:你去银行开户,柜台生成一个账号,系统会自动把这个账号填到你的存折上(keyProperty
就是告诉系统“存到存折的账号栏里”)。
2. keyColumn
作用:告诉 MyBatis:“数据库里生成主键的列名是什么”。
场景:
- 当主键列名和对象属性名不一致时(比如数据库列叫
user_id
,对象属性叫id
)。 - 如果数据库返回多个生成列(比如同时生成订单号和流水号),用逗号分隔,比如
keyColumn="order_no, serial_no"
。
例子:快递单上有一栏叫“运单号”(数据库列),但你的订单对象里叫trackingNumber
(对象属性),keyColumn
就是告诉系统“去快递单的运单号栏找”。
3. resultType
作用:声明 selectKey
中 SQL 返回的主键类型。
细节:
- 简单类型:比如
Integer
(自增ID)、String
(UUID)。 - 多主键:返回
Map
或Object
(比如同时返回订单号和地区码)。
例子:你取快递报手机号,快递员查到的取件码可能是数字(Integer
)或字母+数字组合(String
),resultType
就是告诉系统“取件码的类型是什么”。
4. order
作用:决定“取主键”和“插入数据”谁先谁后。
选项:
BEFORE
:先拿主键,再插入数据(适用于数据库需要提前生成主键,比如 Oracle 的序列)。AFTER
:先插入数据,再拿主键(适用于数据库插入后生成主键,比如 MySQL 自增ID)。
例子:- BEFORE:像电影院选座,先选好座位号(主键),再出票。
- AFTER:像餐馆排队,先点菜(插入数据),等叫号(主键)后再入座。
5. statementType
作用:和之前一样,决定执行 SQL 的工具类型(普通语句、预编译、存储过程)。
细节:
selectKey
里默认用PREPARED
(预编译防注入)。- 除非特殊需求(比如调用存储过程生成主键),否则不用改。
例子:写重要文件时,用模板(PREPARED
)比手写(STATEMENT
)更安全可靠。
MyBatis 映射相关的属性
1. column
作用:数据库表的列名或别名,告诉 MyBatis 从哪一列取数据。
场景:
- 当数据库列名和对象属性名不一致时(比如数据库列叫
user_name
,对象属性叫name
)。
例子:快递单上的“收件人电话”列(column),对应你填写的“手机号”(对象属性)。
2. javaType
作用:指定 Java 对象的类型(比如 String
、Integer
或自定义类)。
细节:
- MyBatis 通常能自动推断类型(比如从
User
对象的name
属性推断为String
)。 - 但如果你用
HashMap
接收数据,必须明确指定javaType
,否则可能类型混乱。
例子:你网购时,快递员默认知道包裹是“电子产品”(自动推断类型),但如果是特殊物品(比如液体),你得明确告知(手动指定类型)。
3. jdbcType
作用:指定数据库字段的 JDBC 类型(比如 VARCHAR
、INTEGER
)。
场景:
- 必须指定当字段允许为空(
NULL
)且参数为null
时,避免 JDBC 类型推导错误。
例子:你寄快递时,如果“保价金额”是可选的,填单子时必须注明“保价类型”(比如数字或货币),否则快递公司可能不知道如何处理空值。
4. typeHandler
作用:自定义类型转换器,处理数据库类型和 Java 类型之间的转换。
场景:
- 默认转换不满足需求时(比如将数据库的
0/1
转成boolean
)。
例子:数据库用字符串"Y"/"N"
表示是否会员,而 Java 用boolean
,这时可以写一个转换器自动处理。
5. select
作用:通过另一个查询(select
语句)加载复杂属性(比如关联对象)。
场景:
- 用于“延迟加载”关联数据(比如查用户时,关联查询他的订单列表)。
风险:可能引发“N+1 查询问题”(查 1 个用户,触发 N 次订单查询)。
例子:查学生信息时,用到班级信息,可以单独写一个select
查询班级表。
6. resultMap
作用:引用一个复杂的结果映射,处理多表联查或嵌套对象。
场景:
- 替代多次
select
查询,一次性通过联查 SQL 加载所有数据。
例子:查询订单时,联查用户和商品表,把结果一次性映射到Order
对象的user
和product
属性中。
7. name
作用:指定构造方法参数的名称(3.4.3+ 版本支持),解决构造函数参数顺序问题。
场景:
- 当类有多个构造方法参数,且顺序不固定时,按名字匹配而非顺序。
例子:你组装家具时,说明书说“先装螺丝A,再装螺丝B”,但如果你有标签(name
),可以直接按标签名称装,不用管顺序。
避坑指南
-
column 别名:
SQL 中如果用了别名(比如SELECT user_name AS name
),这里column
要写别名name
。 -
jdbcType 必填场景:
当参数可能为null
时,比如:#{age, jdbcType=INTEGER} <!-- 如果 age 可能为 null -->
-
慎用 select:
虽然方便,但多级select
会导致性能问题(N+1 查询),优先用resultMap
联查解决。 -
typeHandler 配置:
自定义处理器需要注册到 MyBatis,比如:<!-- 全局注册 -->
<typeHandlers>
<typeHandler handler="com.example.MyBooleanTypeHandler"/>
</typeHandlers>
总结
- 简单映射:用
column
+property
(属性名)即可。 - 复杂类型:用
javaType
+typeHandler
或resultMap
。 - 关联查询:
- 简单情况用
select
(但要注意性能)。 - 复杂情况用
resultMap
联查。
- 简单情况用
- 构造方法:用
name
解决参数顺序问题。