MyBatis主配置文件
1. Properties
可以通过resource属性指定properties配置文件,而后,在配置文件中可以通过${}的方式访问properties里的数据
2. Settings
可以通过setting标签来设置属性。
例:
下面的配置可以将数据库中的下划线式命名法映射到POJO类的驼峰命名法。
---------------------------------------------------------------------------------------
效果:
last_name ===> lastName
3. typeAliases
可以通过配置来给类的的全类名取别名
配置别名的两种方式:
- 通过typeAlias标签:
alias标签可以省略,若没设置alias属性的话,则别名默认为类名
- 通过package标签:
指定包名里的所有类都会被设置默认别名,可能出现的问题是,如果指定包里存在着全类名不同但类名相同的类,使用别名时会出现冲突
此时可以使用@Alias注解来为需要的类配置新的别名,从而解决冲突
PS:别名不区分大小写
PS2:mybatis内置别名
别名 | 类型 |
---|---|
_byte | byte |
_short | short |
_int | int |
_integer | int |
_long | long |
_float | float |
_double | double |
_boolean | boolean |
string | String |
byte | Byte |
short | Short |
int | Integer |
integer | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
map | Map |
typeHandler
类型处理器:将数据库的数据类型与Java的数据类型一一对应,mybatis3.4以后就自带处理了,这里就不多学了。
plugins
插件
environments
环境标签,可以通过environment来配置一个具体的环境。在存在多个不同的环境时,可以通过environments的default属性来指定所使用的环境。
environment标签中,有两个标签
transactionManager:事务管理器
type:事务管理器的类型
可选值有JDBC(JdbcTransactionFactory)和MANAGED(ManagedTransactionFactory)
实际上这两个都是实现了TransactionFactory接口的类,通过实现TransactionFactory接口,也可以做到自定义事务管理器,此时type指定为类的全类名。
dataSource:数据源
type:数据源类型
可选值有UNPOOLED(UnpooledDataSourceFactory),POOLED(PooledDataSourceFactory),JNDI(JndiDataSourceFactory)。实质上是实现了DataSourceFactory接口的类。
databaseIdProvider
作用:为sql语句选择使用的数据库,实现了多厂商支持
type:获得各数据库厂商的标识,例如MySQL,Oracle,SQL Server
property子标签可以给这些标识加上别名,然后在编写sql语句的时候就可以在属性指定databaseId这一属性。
=======================================================
用例:
mappers
作用:将写好的sql映射文件注册到mybatis配置文件。
注册映射文件的方法:
- 通过mapper标签:
- resource:类路径
- url:网络路径或磁盘路径
- class:对应接口的路径
PS:使用class属性时,必须要有与接口对应的sql映射文件,而且必须和接口放在同一目录下。
- 通过package标签:
name:指定包名,批量注册指定包里的所有接口 - 不写映射文件,直接通过注解完成sql语句。
PS:如果通过mapper标签的class属性或者通过package标签来注册,同时又想实现接口和映射文件分离,那么可以通过在项目的资源目录resouces下创建和接口相同的包名,用来存放映射文件。这样做的原理是,这两个目录所指向的其实是同一个目录。
映射文件
增删改
- mybatis允许增删改定义以下返回值
int,long,boolean(基础类型、包装类) - 可以不写parameterType
但是写了可以限制传入的参数。 - 如果使用无参的openSession(),增删改操作时,需要手动提交。
- 获取自增主键的值
插入命令时,可以通过将useGeneratedKeys的值设为true,并且用keyProperty来指定用来返回主键值的JavaBean的一个属性。
参数处理
当传入一个参数时,mybatis不会对参数进行处理。
因此不管#{}里面填的是什么,都能取到唯一的参数当传入多个参数时,mybatis会将参数封装成map,如果不指定key的话,则map默认的key值为param1.....paramN,value值则为传入的参数值。
因此取值的时候可以通过#{默认的key值}或者#{索引}来找到对应的值。
但是也可以通过@param("设定的key")来给map设定key值。
用例:
User seleceByIdAndName(@Param("userId") int id, @Param("lastName") String name);
如果传入的多个参数正好是业务逻辑的模型,可以将这些参数封装成一个POJO对象传入
如果传入的多个参数不是业务逻辑的模型,且使用频率不高时,可以构造一个map
如果传入的多个参数不是业务逻辑的模型,但是使用频率很高时,可以编写TO(Transfer Object)数据传输对象。
Page {
int page;
int index;
}当传入的是Collection、List或者Array数组时:
Collection使用collection
List使用list、collection
Array使用array
这几个并不能使用通用的param1等
mybatis封装参数的过程。
- 判断参数的数量,如果为参数为0直接返回。
#{}和${}的区别
两者都是用来获取map中的值或者是POJO类中的属性。
#{}采用预编译的方式,将里面的值设置到sql语句中,类似于PreparedStatement。
${}采用字符串拼接的方式,将里面的值与sql语句进行拼接,有安全问题。
如果遇到原生JDBC都不支持占位符的情况下
比如分表,表名,排序。
select * from ${year}_salary;
select * from ${table_name};
这种情况下只能只用${}
通常情况下#{}比${}要安全,能用#{}的情况下选择用#{}
#{}在取值的时候还能加上其他参数,这里暂时先不学了。
返回值处理
通过resultType来指定返回值的类型
- 返回值是List
此时resultType应该指定的是List中元素的类型,mybatis会把每一条记录封装成user对象,然后返回集合。 - 返回类型为Map
此时resultType是map,mybatis把记录拆成键值的方式封装在map里 - 返回类型是Map
此时resultType应指定为User,因为mybatis是要将记录封装在User对象中,但是如果只指定了resultType,在运行时会报错,报错信息为:
Expected one result (or null) to be returned by selectOne(), but found: 2
需要返回的参数超出了mybatis能返回的数量,这时可以通过@MapKey来给接口中的方法打上注解,可以将JavaBean中的一个属性设定为另一个参数。
自定义返回类型
resultMap:不能和resultType同时使用,自定义封装规则
- type:指定自定义规则的JavaBean
- id:该resultMap的唯一标识符
子标签: :添加主键的映射 :添加其他字段的映射
用column属性指定数据库中的字段,property属性指定JavaBean中的成员。
id也可以用result替代,但是id的优化优于result
字段与JavaBean中成员名相同的,可以不进行映射。
当一个类中包含其他类的引用时,使用级联属性封装结果集
JavaBean(省略成员方法):
======================================
public class User {
private Integer userId;
private String lastName;
private String sex;
private Integer age;
private Class aClass;
}
public class Class {
private int id;
private String className;
}
映射文件:
======================================
这里将d_id字段的值交给了aClass的id属性,class_name交给了className属性。
当一个类中包含其他类的引用时,使用Association封装结果集
JavaBean同上,映射文件改为:
association:
- property中的是JavaBean中被选为Association的属性,这里是aClass
- javaType中的是该属性的Java类型。
这里不把其他字段映射的话,获取不到值
使用association进行分步查询
步骤:
- 通过传入的userId值来获得user的详细信息
- 通过user信息中d_id来查询班级信息
- 将班级信息封装给user的aClass属性
association中:
- select属性指定了要执行的查询语句
- column指定了执行语句所需的参数
分布查询的延迟加载:
仅当关联的属性被使用时,才执行分步的查询语句。
通过在mybatis配置文件中配置lazyLoadingEnabled和aggressiveLazyLoading属性。
该项设为true时,启动延迟加载
该项设为true时,在延迟加载时,一次性加载所有的属性,否则,只加载需要的属性。
返回值中包含集合
返回值中包含集合的时候,使用collection标签来对记录进行封装。
- property:封装成的属性
- ofType:分装成的Java类型
collection内的配置与以往相同。
包含集合的分步查询
步骤:
- 用班级id获取到班级的信息
- 再用班级id在用户表里查找用户。
- fetchType:加载方式:延迟加载或立即加载
PS:当collection里的column要传递多个参数时,可以使用{key1=value1,key2=value2}的方式书写
注:这里第一次看视频教程的时候,视频上用的collection,但是我自己敲的时候不小心敲成association,但是也成功查询到了结果,因此目前有点分不清association和collection了。
动态SQL
if标签的使用
与jstl表达式类似,不过OGNL里test支持的元素更多。
当满足test属性里的条件时,对应的sql语句片段被拼接
select * from tb_user
where
user_id = #{userId}
and last_name like #{lastName}
and sex = #{sex}
and age = #{age}
常用的字符转义符
字符 | 十进制 | 转义字符 |
---|---|---|
" | " | " |
& | & | & |
< | < | < |
> | > | > |
不断开空格(non-breaking space) |
where标签
去掉拼接后字符串前多余的and或者or
PS:
- where标签会自动在拼接体前面加上where
- where标签不能去除后面重复的and或or
trim标签
- prefix:前缀,在拼接体前面加上的前缀
- prefixOverrides:前缀覆盖,去掉拼接体前面多余的字符串
- suffix:后缀,在拼接体后面加上的后缀
- suffixOverrides:后缀覆盖,去掉拼接体后面多余的字符串
select * from tb_user
user_id = #{userId} and
last_name like #{lastName} and
sex = #{sex} and
age = #{age}
choose标签
当满足某一分支的时候选择对应的sql语句,类似于switch-case语句,按顺序判断
select * from tb_user
user_id = #{userId}
last_name like #{lastName}
sex = #{sex}
age = #{age}
set标签
用于更新字段,当用if标签判断需要拼接的字符串时,可能出现多余的",",这个时候可以用set标签来取出多余的","。
update tb_user
last_name = #{lastName},
sex = #{sex},
age = #{age}
user_id = #{userId}
foreach标签
通过遍历可以把集合里的元素生成一个字符串
- collection:用来选中传来的集合参数
- item:表示集合中每个元素
- separator:用来分个每个元素的符号
- open:在集合生成的字符串前面添加的字符串
- close:在集合生成的字符串后面添加的字符串
- index:表示遍历过程中,集合的索引(遍历map时,表示key值)
使用foreach标签插入多条记录
- 通过mysql语句支持 insert into table_name values(),(),()的特点,用foreach标签拼接出来插入多条记录的单sql语句。
insert into tb_user(last_name, sex, age) values
(#{user.lastName}, #{user.sex}, #{user.age})
- 通过foreach拼接处多条用分号分个的insert语句
insert into tb_user(last_name, sex, age)
values(#{user.lastName}, #{user.sex}, #{user.age})
PS:这个方法不限于insert语句,也可以用于其他语句,但是使用这个方法必须在数据库连接url的属性后添加allowMultiQueries=true。
两个内置对象
- _parameter
表示传入sql语句的参数,多个参数时,这些参数会被封装成map,此时_parameter指代的就是这个map - _databaseId
表示当前数据库的id,可以通过这个对象判断当前使用的数据库
bind标签
可以将OGNL表达式的值绑定到一个变量
sql标签
- sql:抽取sql片段,以便后面重用
- include:引入sql标签声明的sql片段。
- include还可以通过property子标签设置自定义属性,可以在sql标签里通过${}直接使用。
insert into tb_user(
)
values(#{user.lastName}, #{user.sex}, #{user.age})
last_name, sex, age