一、mybatis相关介绍
jdbc:编写sql、预编译、设置参数、执行sql、分装结果。功能简单,sql语句写在Java代码里面,采用硬编码高耦合的方式。
Hibernate:全自动全映射ORM(object relation mapping)框架。
优点:消除sql,即使开发人员不懂sql,用框架,开发人员只需要知道javabean对应哪个数据库中的哪个表,也可以完成任务,很省事。
缺点:①开发人员不编写sql,是由框架自己完成,不可以优化,失去了sql的灵活性。②有些复杂的查询需要使用定制的sql,不用框架自己写的,那么就需要学习Hibername中的一项技术,称为HQL,这个技术支持定制sql,这样的话会加重开发人员的学习负担。③如果javabean中有一百个字段,数据库中对应的表中的记录会有一百列与javabean中的字段对应,如果只想查一个字段,此时做不到,一查就是一百个字段。
二、全局配置文件
1、标签properties来引入properties配置文件的内容
resource属性:引入类路径下的资源;
url属性:引入网络路径或磁盘路径下的资源;
2、settings包含很多重要的设置项
setting子标签:用来设置每一个设置项
name属性:设置项名
value属性:设置项值
例如:
< settings>
<setting name= "mapUnderscoreTocamelCase" value= "true"/>
< / settings>
3、typeAliases别名处理器,可以为Java类型起别名,注意别名不区分大小写
typeAlias子标签:为某个java类型起别名。
type属性:指定要取别名的类型的全类名,默认别名是类名小写。
Alias属性:指定新的别名。
package子标签:为某个包下的所有类批量起别名
name属性:指定包名(为当前包以及下面所有的后代包的每一个类都起一个 默认别名(类名小写))
注:①批量起别名的情况下,如果当前包与其子包都有一个名字相同的bean,则会造成两者的别名一样,产生别名冲突,运行报错,此时可以使用@Alias(“ ”)注解为某个类型指定新的别名,将该注解放在类名之上。
②基本类型的默认别名都是_xxx。
4、environments:在mybatis中可以配置多种环境。
default属性:指定使用某种环境,可以达到快速切换环境的效果。
environment子标签:配置一个具体的环境信息。
id属性:表示当前环境的唯一标识,常与父标签的default的属性值相匹配。
transactionManager子标签:事务管理器。
type属性:事务管理器的类型,有两种取值,分别为JDBC|MANAGED。
JDBC指使用jdbc的方式进行事物的控制。(别名)
MANAGED指使用jee服务器容器的方式进行事物的控制。(别名)
dataSource子标签:数据源。
type属性:数据源的类型,有三种取值,分别为UNPOOLED|POOLED|JNDI。UNPOOLED指不使用连接池技术,每一次增删改查都会从数据库中拿 一次新的连接,而不是用连接池。POOLED指使用连接池技术。
5、mappers:将sql映射注册到全局配置中。
mapper子标签:注册一个具体的sql映射。
resource属性:引用类路径下的sql映射文件。
url属性:引用网络路径下或者磁盘路径下的sql映射文件。
class属性:引用注册接口。
①如果有sql映射文件,则保证映射文件名必须和接口同名,并且放在 与接口统一目录下。
②没有sql映射文件,所有sql都是利用注解写在接口上。
public interface EmployeeMapperAnnotation {
@Select( "select * from tbl_employee where id=#{id}")
public Employee getEmpById ( Integer id);
}
package子标签:批量注册。
name属性:包名。
注意:各个标签的排放顺序properties?, settings?, typeAliases?, typeHandlers?, objectFactory?,
objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?,
mappers?
三、映射文件
1、mapper
namespace属性:(旧)名称空间,随便起名,(新)指定为接口的全类名
select子标签
id属性:这个标签的唯一标识
resultType属性:返回值类型(查出的结果封装成一个对象)
#{id}:从传递过来的参数中取出id值
2、insert
useGeneratedKeys属性:用来获取主键值,值为true,
keyProperty属性:指定对应的主键属性,也就是获取到主键值后,将这个值封装到javaBean中的哪个属性中。
<insert useGeneratedKeys="true" keyProperty="id">
3、映射文件中的参数处理
【1】单个参数:mybatis不会做特殊处理,用#{参数名}取出参数值
多个参数:mybatis会做特殊处理,多个参数被封装成一个map,key:param1...paramN或者索引也可以(0....n),Value:传入的参数值,#{}就是从map中获取指定的key值。但是此时如果参数过多,则会出现混乱的情况,此时要用命名参数,明确指定封装参数时map的key,使用注解@param,此时当多个参数被封装成一个map时,key:使用注解@param指定的值,value:参数值,#{指定的key}就可以取出对应的参数值。
【2】如果多个参数正好是业务逻辑的数据模型(bean),直接传入pojo(对象)即可,#{}就可取出传入pojo属性值,如果多个参数不是业务模型中的数据,没有对应的pojo,而且不经常使用,这时可以传入map,#{key}就可以取出map对应的值。
【3】如果参数时Collection类型或是数组,则mybatis也会做特殊处理,把传入的list或数组封装到map中,如果是Collection,则key:collection,如果是List,key:list,如果是数组,key:array。
4、参数值的获取,#{}与${}的区别
#{}是以预编译的形式,将参数设置到sql语句中,防止sql注入
${}取出的值直接拼装在sql语句中,会有安全问题
大多数情况使用#{}去取参数的值,对于原生jdbc不支持占位符的地方,我们就可以使用${}进行取值,比如select * from ${year}_salary where xxx。
5、select
resultType属性:如果要返回的是集合类型,那么返回值是集合中的元素类型,如 果要返回的是Map类型,那么返回是map。
resultMap属性:引用resultMap标签,其值要和resultMap标签中的id属性对应。
6、resultMap:自定义结果集映射。
type属性:自定义规则的java类型。
id属性:唯一的,方便引用。
id子标签:指定主键列的封装规则。
column属性:指定哪一列。
property属性:指定对应的JavaBean属性。
result子标签:指定普通列封装规则,其他不指定的列会自动封装。
column属性:指定哪一列。
property属性:指定对应的JavaBean属性。
association子标签:可以指定联合的javaBean对象。
property属性:指定哪个属性是联合的对象。
javaType属性:指定这个属性对象的类型(不可省略)。
select属性:表明当前属性是调用select指定的方法查出的结果。
column属性:指定将哪一列的值传给这个方法。
id子标签:指定主键列的封装规则。
column属性:指定哪一列。
property属性:指定对应的JavaBean属性。
result子标签:指定普通列封装规则,其他不指定的列会自动封装。
column属性:指定哪一列。
property属性:指定对应的JavaBean属性。
collection子标签:定义关联集合类型属性的封装规则。
ofType属性:指定集合里面元素的类型。
property属性:指定联合的javaBean中的集合属性。
id子标签:指定主键列的封装规则。
column属性:指定哪一列。
property属性:指定对应的JavaBean属性。
result子标签:指定普通列封装规则,其他不指定的列会自动封装。
column属性:指定哪一列。
property属性:指定对应的JavaBean属性。
1)、联合属性可以采用级联封装结果集
2)、采用association标签分装结果集
流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性。
四、动态SQL
1、if,判断
test属性:判断表达式(ognl),从参数中取值判断。ognl会进行字符串和数字之间的判断,例”0”==0。
注:查询的时候如果某些条件没带可能sql拼装会有问题
①给where后加上1=1,以后的条件都是and xxx。
②mybatis使用where标签将所有的查询条件包括在内,mybatis就会将where标签中拼装的sql,多出来的and或or去掉,但是where只会去掉第一个多出来的and或者or,后面多出的and或or,where标签不能解决。
2、trim,自定义字符串的截取规则,标签体中是整个字符串拼串后的结果。
prefix属性:前缀,给拼串后的整个字符串加一个前缀。
prefixOverrides属性:前缀覆盖,去掉整个字符串前面多余的字符。
suffix属性:后缀,给拼串后的整个字符串加一个后缀。
suffixOverrides属性:后缀覆盖,去掉整个字符串后面多余的字符。
3、foreach
collection属性:指定要遍历的集合。
item属性:将当前遍历出的元素赋值给指定的变量。
separator属性:每个元素之间的分隔符。
open属性:遍历出所有结果拼接一个开始的字符。
close属性:遍历出所有结果拼接一个结束的字符。
index属性:索引,遍历list的时候是索引,遍历map的时候是map的key,item就是值。
五、缓存
一级缓存:又称为本地缓存,是sqlSession级别的缓存,并且是一直开启的,人为无法关闭。
【1】工作机制:与数据库同一次会话期间查询到的数据会放在本地缓存中。以后如果需要获 取相同的数据,不会再次查询数据库,而是会直接从缓存中拿。
【2】一级缓存失效的情况:
①sqlSession不同。
②sqlSession相同,但查询条件不同。(当前一级缓存还没有这个数据)
③sqlSession相同,两次查询之间执行了增删改操作。(这次增删改可能对当前数据有 影响)
④sqlSession相同,手动清除了一级缓存。(缓存清空)
二级缓存:全局缓存,基于namespace级别的缓存,一个namespace对应一个二级缓存。
【1】工作机制:
一次会话,查询一条数据,这个数据就会被放在当前会话的以及缓存中。
如果会话关闭,一级缓存中的数据会被保存到二级缓存中。此时新的会话查询信息, 就可以参照二级缓存中的内容。
不同namespace查出的数据会放在自己对应的缓存中(map)。
【2】使用:
开启全局二级缓存配置。
去中配置使用二级缓存<cache><cache/>。
pojo需要实现序列化接口。
注意:查出的数据都会默认先放在一级缓存中,只有当会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中。