MyBatis学习

MyBatis学习

MyBatis简介

JDBC存在的问题
  1. 数据库连接创建、释放频繁造成系统资源浪费,可以使用数据库连接池
  2. sql语句在代码中硬编码
  3. 使用preparedStatement向占位符穿参数存在硬编码
  4. 对结果集解析存在硬编码,sql变化导致解析代码变化

可以借助第三方工具DBUtils或者Spring中自带的数据库操作框架JdbcTemplate

框架MyBatis或者Jpa

MyBatis介绍

iBatis改进而来,对jdbc的操作数据库的过程进行封装

通过xml或注解的方式将要执行的各种statement配置起来,通过java对象和statement中的sql进行映射生成最终执行的sql语句,由mybatis框架执行sql并将结果映射成java对象并返回

将java方法与sql语句关联

允许用户充分利用数据库的各种功能

官方有中文版

HelloWorld
  1. 创建数据库
  2. 创建一个普通的maven工程
  3. 项目创建完成之后,添加MyBatis依赖
  4. 准备一个Mapper文件,Mapper是用来在MyBatis中定义SQL的XML配置文件。可以将Mapper文件做成一个模板
    1. 取一个分隔符namespace,不可重复
    2. 定义一个简单的查询方法
    3. resultType定义了返回值的类型,#{}表示这个位置用来接收外部传进来的参数
  5. 创建MyBatis配置文件,参考官网,拷贝一下配置文件的头信息
  6. 加载主配置文件
    1. 生成一个SqlSessionFactory
    2. SqlSessionFactory生成一个SqlSession,SqlSession相当于一个会话,类似JDBC的一个连接
    3. SqlSession中封装了对数据库的操作,面向用户的接口
    4. 使用完毕要关闭它

增删改查

  1. 自增长
  2. Java代码传一个ID进来,这个ID可以是一个UUID,也可以是其他的自定义的ID
  • 主键自增长,parameterType表示传入的参数类型。参数通过#来引用
  • 使用UUID做主键
    • 在java代码中生成UUID,直接作为参数传入到SQL中
    • 使用MySQL自带的UUID函数生成UUID
      • ResultType表示查询结果的返回类型
      • keyProperty属性表示将查询的结果赋值给传递进来的User对象的id属性
      • order表示这个查询操作的执行实际,BEFORE表示这个查询操作在insert之前执行
      • selectKey表示查询key
  1. 在UserMapper中定义删除SQL
  2. 在Java代码中调用该方法
  1. 定义SQL
  2. 在Java代码中调用
  1. 定义SQL
  2. 在Java代码中调用

MyBatis架构介绍

  1. mybatis配置:mybatis-config.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。另一个mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在mybatis-config.xml中加载
  2. 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
  3. 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSesstion即会话工厂
  4. mybatis底层自定义了Executor执行器接口操作数据库,Excuetor接口有两个实现,一个是基本执行器,一个是缓存执行器
  5. Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息即sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id
  6. Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数
  7. Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程
Mybatis解决的问题
  1. 在mybatis-config.xml中配置数据库连接池,使用连接池管理数据库连接
  2. 将sql语句配置在mapper.xml文件中与java代码分离
  3. Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型
  4. Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型

引入Mapper

优化的地方:

  1. 每个方法都需要获取SqlSession
  2. 涉及增删改的地方,需要commit
  3. sqlSession主要关闭,sqlSession执行时需要的参数就是方法的参数,sqlSession要执行的Sql,和XML中的定义是一一对应的。模板化程度较高

解决:动态代理

  1. 将当前方法简化成一个接口
  2. 接口对应的Mapper文件

接口可以自动生成Dao

  • UserDao中定义了SqlSessionFactory
  • UserMapper所在包+UserMapper类名+UserMapper中定义好的方法名。可以定位到调用的SQL
  • 根据SQL节点可以定位到SqlSession中的方法
  1. 在MyBatis的全局配置中,配置一下UserMapper
  2. 加载配置文件,获取UserMapper,调用里面的方法

maven要求将XML配置、properties配置等,都放在resources目录下,如果强行放在java目录下,默认情况下,打包时这个配置文件会被自动忽略

  • 在pom.xml中添加配置
  • 将xml文件放在resources目录下
    • mybatis中默认情况要求,Mapper.xml和mapper接口,必须放在一起,需要手动在resources目录下,创建一个和UserMapper接口相同的目录

全局配置

properties

引入一个外部配置,一如数据库配置

利用mybatis-config.xml配置文件中额properties属性,引入这个配置文件,然后再DataSource中石油这个配置文件

settings
typeAliases

MyBatis中定义的别名,一种是MyBatis自带的别名,一种是自定义的别名

MyBatis自带的别名

byte------>_byte

long------>Long

int------>Integer

定义数据类型的路径,可以用类型的别名代替

自定义的别名

添加typeAliases节点

批量给对象定义别名,批量定义主要利用包扫描来做,批量定义默认的类的别名,是类名首字母小写

最新版中,批量定义的别名,类名首字母可以不小写,实际开始,一般使用批量定义

typeHandlers

mybatis映射中,能自动的将jdbc类型映射为java类型。

特殊类型,需要自定义类型处理器

  1. 数据存储时
  2. 数据查询时,转换类型

读取配置:

  1. 在ResultMap中做局部配置
  2. 在全局配置中进行配置
mapper配置

Mapper映射文件

parammeterType

表示输入的参数类型

$和#

在MyBatis中,在mapper中引用变量时,默认使用的是#

select * from user where id=#{id};

除了使用#,也可以使用$来引用一个变量

select * from user where id=${id};

在就的MaBatis版本中,如果使用KaTeX parse error: Expected 'EOF', got '#' at position 34: …最新的MyBatis中,无论是#̲还是,如果只有一个参数,可以不用取别名

$和#的区别

$:SQL直接拼接好,没有参数。相当于是参数拼接的方式,存在SQL注入的风险,使用较少

#:使用预编译的方式。相当于是占位符的方式

有的SQL无法使用#来拼接,例如传一个动态字段进来,查询所有数据,排序查询,但是排序的字段不确定,需要通过参数传入,这种场景只能使用$

面试时,一定要答出Statement和PreparedStatement之间的区别

简单类型

简单数据类型传递比较容易

根据id查询一条记录

给参数添加@Param来指定参数名

在xml文件中,就不用定义parameterType了,在mapper.xml文件中,就可以直接使用username和id来引用变量

对象参数

如果给对象添加了@Param注解,对象属性的引用,会有一些变化,Mapper中的写法会发生变化

多一个前缀,这个前缀是@Param注解中定义名称

如果对象中还存在对象,用.继续访问

Map参数

一般不使用Map参数

引用的变量名,就是map中的key.如果map取了别名,在引用的时候,也要讲别名作为前缀加上

resultType

返回类型,如果返回的数据类型比较复杂,一般使用resultMap,对于一些简单的返回,使用resultType

resultType返回的类型:简单类型,对象,集合,hashmap等

输出pojo对象和输出pojo列表在sql中定义的resultType是一样的。返回单个pojo对象要保证sql查询出来的结果集为单条,事宜sqlSession.selectOne方法调用,mapper接口事宜pojo对象作为方法返回值,返回pojo列表表示查询出来的结果集可能为多条,内部事宜sqlSession.selectList方法,mapper接口事宜List对象作为方法返回值

resultMap

自己定义映射的结果集

id:描述主键,column:数据库查询出来的列名,property:对象中的属性名

在查询结果中,定义返回值时事宜这个ResultMap

在旧版MyBatis中,要求实体类一定要有一个无参构造方法

也可以在resultMap中,自己指定要调用的构造方法

动态SQL

例如查询条件不确定,批量插入等等

if

如果满足某个条件,节点中的SQL就会生效

test表示判断条件

where

处理查询参数

每个参数都是可选的

where节点将所有查询条件包起来,如果有满足的条件,where节点会自动加上,如果没有,where节点不会存在,在满足条件的秦光霞,where会自动处理and关键字

foreach

用来处理数组、集合参数

<foreach collectioon="ids" open="(" close=")" item="id" separator=",">

foreach节点遍历数组,collection表示数组变量,open表示循环结束后,左边的符号,close表示循环结束后,右边的符号,item表示循环时候的单个变量,separator表示循环的元素之间的分隔符

默认情况下,无论数组/集合参数名字是什么,在xml中访问的时候,都是array,开发者可以通过@Param注解给参数重新指定名字

sql片段

sql查询中,一般不建议写*,会降低查询效率。每次查询都要把字段名列出来,太麻烦,可以使用SQL片段来解决问题

现在mapper中定义一个SQL片段

在其他SQL中,引用这个变量

set

一般用在更新中,如果对象中存在该字段的值,就更新该字段,不存在,就不更新

一对一查询

resultMap来定义查询结果的映射关系

association节点来描述一对一的关系

在实际项目中,每次返回的数据类型可能都会有差异,需要定义多个resultMap,这多个resultMap中,又有一部分属性是相同的,可以将相同的部分抽出来,做成一个公共的模板,然后被其他resultMap集成

在查询SQL中,先做好一对一查询,然后,返回值定义成resultMap,在resultMap中,定义查询结果的映射关系

association描述一对一关系,在这个节点中的内容,和resultMap一样

懒加载

一对一的属性使用得不是很频繁,可以启用懒加载

先查询book,在查询book的过程中,不查询author,当用户第一次调用量book中的author属性后,再去查询author

定义association的时候,不直接指定映射的字段,而是指定要执行的方法,通过select字段指定,column表示执行方法时传递的参数字段,最后的fetchType表示开启懒加载

一对多查询

在resultMap中,通过collection节点来描述集合的映射关系。在映射时,会自动将一方的数据集合并,然后将多的一方放到集合中

查询缓存

Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存,第二次会从缓存中获取数据将不再从数据库查询,提高查询效率

当一个sqlSession结束后还sqlSession中的一级缓存就不存在了。Mybatis默认开启一级缓存

多次查询,只执行一次SQL,必须是同一个SqlSession中,缓存才有效

Mybatis二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlsession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存,第二次会从缓存中获取数据将不再从数据库查询。

Mybatis默认没有开启二级缓存,在setting全局参数中配置开启二级缓存

逆向工程

高查询效率

当一个sqlSession结束后还sqlSession中的一级缓存就不存在了。Mybatis默认开启一级缓存

多次查询,只执行一次SQL,必须是同一个SqlSession中,缓存才有效

Mybatis二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlsession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存,第二次会从缓存中获取数据将不再从数据库查询。

Mybatis默认没有开启二级缓存,在setting全局参数中配置开启二级缓存

逆向工程

使用数据表是,我们需要给每个表都创建相应的实体类,每个实体类都有对应的mapper接口和mapper.xml文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值