MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
随谈目前我只是简单的讲解mybatis的使用,如果想学到更多可以去:https://mybatis.net.cn/
这是mybatis中文文档,所以的mybatis操作都可以在上面找到,还有很多源码之类的分析
入门 打开idea,创建一个maven项目 导入依赖的jar包
mysql
mysql-connector-java
5.1.47
org.mybatis
mybatis
3.5.7
junit
junit
4.12
org.projectlombok
lombok
1.18.12
provided
com.github.pagehelper
pagehelper
5.1.6
maven资源导出问题(约定大于配置)
src/main/resources
***.xml
true
src/main/java
***.xml
true
maven解决utf-8乱码问题
全局配置UTF-8
必须按照如下顺序来配置子标签
子标签 我讲的不全 可以去看 https://mybatis.net.cn/configuration.html#databaseIdProvider < properties > 属性//(配置)
用来调用properties文件,用${}占位符来快速引用数据源的消息
< settings > 设置
开启延迟加载(懒加载): 解决n+1问题
开启二级缓存(全局缓存)
开启日志
< typeAliases > 类别别名//自带的日志 //log4j日志 需要导jar包和配置log4j的资源 log4j.properties 文件
取别名(一般来说给实体类取别名就行了)
//第一种方式 自定义< typeHandlers > 类别处理器//第二种方式 mybatis自己配置 可以给自己的配置类取别名 别名就是 实体类名字 第一个字母为大写其他小写 //如:第一个方法的 Student 实体类 在com.zhao.pojo包下 别名就是Student
用于处理 Java 类型和 Jdbc 类型之间的转换,用的不多可以不管
< objectFactory > 对象工厂用于创建对象实例,用的不多可以不管
< plugins > 插件可以用来配置mybatis的插件,比如pageHelper分页插件:
< environments > 环境配置 **< transactionManager > ** 事务管理器
在 MyBatis 中有两种事务管理器类型(也就是 type=”[JDBC|MANAGED]”):
JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。 它依赖于从数据源得 到的连接来管理事务范围。
MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让 容器来管理事务的整个生命周期(比如 Spring 或 JEE 应用服务器的上下文) 默认 情况下它会关闭连接。 然而一些容器并不希望这样, 因此如果你需要从连接中停止 它,将 closeConnection 属性设置为 false。
< dataSource > 数据源
POOLED:采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现
UNPOOLED:采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。
JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样
//环境变量
//事务管理器
//数据源
< databaseldProvider > 数据库厂商标识
MyBatis 可以根据不同的数据库厂商执行不同的语句,用的不多可以不管
< mappers > 映射器用来配置 mapper.xml 映射文件
mapper class : 可以自动映射同一个类下同一个名字的mapper.xml文件 :比如我的 dao 类下有个 叫 UserMapper 的接口文件和 UserMapper.xml文件,就可以映射到这个文件
mapper resource : 就是很笨的导入 UserMapper.xml 文件
package name :就是自动扫描 我写的 dao 下面的所有 Mapper.xml 文件
注解开发
我感觉CRUD没啥必要用注解,现阶段可以多手敲,而且如果要后期调配啥的注解很难得找(就是很难维护)没有直接写在Mapper.xml文件里面好找
值得一提的是 @Param 注解,若需要传入多个参数,可以结合 @Param 注解
如:@Param(“uid”) int id 在mapper.xml文件中写sql时 只需要用 #{uid} 把传递参数时就可以把 id 值传给sql语句
@Select("select * from user")
List getUsers();
@Delete("deelete from user where id = #{uid} and name = #{uname}")
int dedleteUser(@Param("uid") int id,@Param("uname") String name);
主键返回
1.使用 useGeneratedKeys 和 keyProperty 属性
insert into smbms_address (contact,addressDesc,tel) values (#{contactName},#{desc},#{phone})
2.使用**< selectKey >**子标签
insert into smbms_address (contact,addressDesc,tel) values (#{contactName},#{desc},#{phone}) SELECT LAST_INSERT_ID();
此时可以用**< selectKey >标签,设置其order属性为BEFORE**,并在标签体内写上生成主键的SQL语句,这样在插入之前,会先处理**< selectKey >**,生成主键,再执行真正的插入操作。
**< selectKey >**标签其实就是一条SQL,这条SQL的执行,可以放在主SQL执行之前或之后,并且会将其执行得到的结果封装到入参的Java对象的指定属性上。注意 **< selectKey >子标签只能用在< insert >和< update >**标签中。上面的 LAST_INSERT_ID() 实际上是MySQL提供的一个函数,可以用来获取最近插入或更新的记录的主键id。
关联查询(一对多,多对一)查询 多对一:对象:association 解决问题(实体类中:一个实体类对应另一个实体类):private Teacher teacher;
一对多:集合:collection
解决问题(实体类中:一个实体类对应一个List):private List< Student > students;
动态SQLselect s.id sid,s.name sname,t.name tname,t.id tid from student s,teacher t where s.tid = t.id and t.id = #{id}
比如在以前的开发中,由于不确定查询参数是否存在,许多人会使用类似于where 1 = 1 来作为前缀,然后后面用AND 拼接要查询的参数,这样,就算要查询的参数为空,也能够正确执行查询,如果不加1 = 1,则如果查询参数为空,SQL语句就会变成SELECT * FROM student where,SQL不合法。
ifchooseSELECT * FROM student WHERe age >= 18 AND name like '%${name}%'
trim:基本使用where和set whereSELECT * FROM BLOG WHERe state = ‘ACTIVE’ AND title like #{title} AND author_name like #{author.name} AND featured = 1
标签只会在至少有一个子元素返回了SQL语句时,才会向SQL语句中添加WHERe,并且如果WHERe之后是以AND或OR开头,会自动将其删掉
setSELECT * FROM BLOG state = #{state} AND title like #{title} AND author_name like #{author.name}
在至少有一个子元素返回了SQL语句时,才会向SQL语句中添加SET,并且如果SET之后是以,开头的话,会自动将其删掉
sqlupdate mybatis.blog where id=#{id} title=#{title}, author=#{author}
可将重复的SQL片段提取出来,然后在需要的地方,使用**< include >**标签进行引用,实现了代码的复用
bindSELECT * FROM user AND username like '%${user.name}%'
mybatis的动态SQL都是用OGNL表达式进行解析的,如果需要创建OGNL表达式以外的变量,可以用bind标签
foreachSELECT * FROM BLOG WHERe title LIKE #{pattern}
用来做迭代拼接的,通常会与SQL语句中的IN查询条件结合使用,注意,到parameterType为List(链表)或者Array(数组),后面在引用时,参数名必须为list或者array。如在foreach标签中,collection属性则为需要迭代的集合,由于入参是个List,所以参数名必须为list
缓存 一级缓存SELECT * FROM student WHERe id in #{item}
默认开启,同一个SqlSesion级别共享的缓存,在一个SqlSession的生命周期内,执行2次相同的SQL查询,则第二次SQL查询会直接取缓存的数据,而不走数 据库,当然,若第一次和第二次相同的SQL查询之间,执行了DML(INSERT/UPDATE/DELETE),则一级缓存会被清空,第二次查询相同SQL仍然会走数据库
一级缓存在下面情况会被清除
在同一个SqlSession下执行增删改操作时(不必提交),会清除一级缓存
SqlSession提交或关闭时(关闭时会自动提交),会清除一级缓存
对mapper.xml中的某个CRUD标签,设置属性flushCache=true,这样会导致该MappedStatement的一级缓存,二级缓存都失效(一个CRUD标签在mybatis中会被封装成一个MappedStatement)
在全局配置文件中设置 < setting name=“localCacheScope” value=“STATEMENT”/>,这样会使一级缓存失效,二级缓存不受影响
二级缓存默认关闭,可通过全局配置文件中的< settings name=“cacheEnabled” value=“true”/>开启二级缓存总开关,然后在某个具体的mapper.xml中增加< cache />,即开启了该mapper.xml的二级缓存。二级缓存是mapper级别的缓存,粒度比一级缓存大,多个SqlSession可以共享同一个mapper的二级缓存。注意开启二级缓存后,SqlSession需要提交,查询的数据才会被刷新到二级缓存当中
插件:PageHelper分页插件 注意:在编写mapper.xml的时候,SQL语句的结尾不要带上;,因为PageHelper插件是在SQL末尾拼接LIMIT关键字来进行分页的,若SQL语句带上了;,就会造成SQL语法错误 在pom.xml配置maven依赖在mybatis全局配置文件里面添加插件的标签com.github.pagehelper pagehelper 5.1.6
测试类
@Test
public void test1(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
PageHelper.startPage(2,3); //第二页,三条数据
List users = mapper.test1();
users.forEach(System.out::println);
sqlSession.close();
}
结果
我用了日志,出了红色框中的选项,其他的都是日志,日志也就是使用了动态代理,看java执行了哪些操作



