框架一般都是有配置文件的,看官网文档最好。
Mybatis的学习:https://mybatis.org/mybatis-3/zh/getting-started.html
一、简介
基础:JDBC/Mysql/java基础/Maven/Junit
本来是aoache的一个开源项目ibatis,现在存于github
MyBatis 是一款优秀的持久层框架
它支持自定义 SQL、存储过程以及高级映射
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
maven仓库下载/github下载
持久化
数据持久化:持久化就是将程序的数据在持久状态和瞬时状态转化的过程
内存:断电即失、价格昂贵,因为有一些对象不能丢掉,所以需要持久化。
持久化:数据库(JDBC)、io文件持久化
- 持久层
Dao层/Service层/Controller层
完成持久化工作的代码,层界限十分明显。
- MyBatis的存在意义:
方便,更容易上手,灵活
传统的JDBC代码太复杂,需要简化。Mybatis是一个框架,可以自动化生成
将数据存入到数据库中,sql和代码分离,提高了可维护性;提供映射标签,支持对象和数据库的orm字段关系对应;提供对象关系映射标签,支持对象关系组件维护;提供xml标签,支持编写sql。
二、写一个程序
思路:搭建环境–导入mybatis–编写代码–测试
1.mysql中创建数据库资源
2.idea中新建一个普通的maven项目
3.删除src目录(以后只需要在父工程下创建module就会继承父工程的所有maven依赖)
4.导入maven依赖:mysql/mybatis/junit
5.创建一个新的module。
(每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。有了 SqlSessionFactory,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。)
在新module下的resource下新建一个xml配置文件,在官网上找到相关的配置复制进去,environments中可以配置多个环境。配置的url可以连接到数据库中查找,?后可以添加相关的配置,&需要用&;转义。(中间不要加中文注释)
例如:jdbc:mysql://127.0.0.1:3306/jsh_erp?useUnicode=true&characterEncoding=utf-8&useCursorFetch=true&defaultFetchSize=500&allowMultiQueries=true&rewriteBatchedStatements=true&useSSL=false
也可以不使用 XML 构建 SqlSessionFactory
6.创建一个utils工具类(查看官方文档有具体方法)
静态初始化模块sqlSessionFactory,静态方法得到SqlSession
- 编写代码:
以前:实体类pojo/Dao接口/接口实现类
现在:接口实现类由原来的UserDaoImpl转变为一个Mapper配置文件
8.测试:
可能存在的错误:
在MapperRegistry中,类型接口是未知的(每一个Mapper.xml都需要在Mybatis核心配置文件中注册,这里的路径是/ 不能是.)
在maven的pom.xml中Build中配置resources,防止我们的资源导出失败的问题
绑定的接口错误:namespace中的包名要和Dao/Mapper接口中的名字一致(必须要用. 不能用/)
方法名不对:id就是对应namespace中的方法名
返回类型不对:resultType是sql语句执行的返回值
参数类型:parameterType
标签不要匹配错误
NullPointerException空指针异常是因为sqlSessionFactory搞了两个
输出的xml文件中存在乱码问题:设置为UTF-8
最后用junit测试
三、CRUD
#{} 相当于是占位符 全限定名 别名
#{} 是 占位符 :动态解析 -> 预编译 -> 执行 #{} 对应的变量会自动加上单引号 #{} 能防止sql 注入 #{} 默认值 arg0、arg1、arg2 或 0、 1
${} 是 拼接符 :动态解析 -> 编译 -> 执行 ${} 对应的变量不会加上单引号 ${} 不能防止sql 注入 ${} 默认值param1、param2、param3
使用:
1.能用 #{} 的地方就用 #{},尽量少用 ${}
2.表名作参数,或者order by 排序时用 ${}
3.传参时参数使用@Param(“”)注解,@Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值(相当于又加了一层密),正确的将参数传入sql语句中(一般通过#{}的方式,${}会有sql注入的问题)。如下:
1 | Role selectById(@Param("id") String id); |
增删改需要提交事务:sqlSession.commit();
参数为int可以不用写
当报错的时候,读错要从后往前读
万能的Map:如果实体类中的属性有很多个,或者数据库的表/字段/参数过多时,可能直接传对象的属性不现实。所以可以使用map随意制造参数,通过键值对来传递(相当于是再new一个map,然后put参数,参数值,调用时候直接传map。会自动获取map参数对应的而参数值)。
Map传递参数,直接再sql中取出key即可。parameterType=“map”
对象传递参数,直接再sql中取对象的属性即可。parameterType=“object”
只有一个基本类型参数的情况下,可以直接再sql中取到。
多个参数可以用map,也可以用注解。
模糊查询:拼接参数的时候,防止sql注入的问题
1.java代码执行的时候,#{value} 参数中传递通配符 %*%
2.在sql拼接中使用通配符“%”+#{value}+“%”
四、配置解析
1.核心配置文件
Mybatis-config.xml(官方建议取这个名字)
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
介绍可以参考:https://blog.csdn.net/wuyuxing24/article/details/89343951
MyBatis 允许你在映射语句执行过程中(这个过程就是sqlsession)的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可
利用插件可以完成 分页,动态填入update_by,update_time,create_by,create_time,del_flag字段,拦截sql语句使增删改功能不生效 等功能。
例子:拦截sql语句使增删改功能不生效
1 | //将拦截器注册进spring |
给数据模型的一些通用操作属性(如:创建人、创建时间、修改人、修改时间等)自动赋值
1 | /** |
分页例子参考这篇文章:https://blog.csdn.net/liang0000zai/article/details/102862284
environments(环境配置)
environment(环境变量)
T ransactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
sqlsession
SqlSession是Mybatis最重要的构建之一,可以简单的认为Mybatis一系列的配置目的是生成类似 JDBC生成的Connection对象的SqlSession对象,这样才能与数据库开启“沟通”,通过SqlSession可以实现增删改查(当然现在更加推荐是使用Mapper接口形式)
SqlSessionInterceptor 是 SqlSessionTemplate 的内部类,目的只有一个,就是处理多个 session 的db操作!
所有请求都被 invoke() 拦截,从而做相应处理:
进入请求,先生成一个新的sqlSession,为本次db操作做准备;
通过反射调用请求进来的方法,将 sqlSession 回调,进行复杂查询及结果映射;
如果需要立即提交事务,do it;
如果出现异常,包装异常信息,重新抛出;
操作完成后,关闭本次session;
sqlSession 单例,并不会影响具体的db操作控制,所以不用担心session的线程安全问题
sql语句的where问题
where后面加< if >的标签:
如果if存在的话,会直接连and,导致出现 where and 的错误语句
如果if不存在的话,会直接多出来where,导致错误语句
1.给where 后面加上1=1,以后的条件都可以正常and
2.mybatis 使用where 标签将所有的查询条件包括在内。
mybatis 就会将where标签后面第一个and 去掉(where只会去掉第一个多出来的and 或者 or)
where 1=0: where 后面跟一个永远不可能成立的条件1<0 , 1=0,1=2 这条sql语句结果不会返回任何数据,只有表结构,可用于快速建表
sql语句的模糊查询字符串拼接
1.利用concat进行拼接
1 | SELECT max(gateway_num) from gateway WHERE gateway_num LIKE concat('%',#{num},'%') |
2.动态sql中的bind(未测试)
1 | List<Hospital> getHospitalLike(@Param("selectword") String selectword); |