1.数据库的环境切换
2.注解方式
## 推荐使用xml
a.将sql语句写在接口的方法前面
b.将接口的全类名写入到,让mybatis知道sql语句此时是存储在接口中的。
注意:注解和XML都支持批量引入
3.增删改的返回问题
- 返回值 可以是void ,Integer,Long,Boolean,只需要在接口中改返回值就可以了!
4.事务提交方式
- 手动提交:
SqlSession session = sessionFactory.openSession();
session.commit();//执行完commit时,手动提交 事务
- 自动提交 :每一个dml语句自动提交
SqlSession session = sessionFactory.openSession(true);
5.参数问题
目前将多个参数封装到一个javabean对象(pojo),然后使用该对象传递
-
a.传入多个参数时,不用在mapper.xml中编写parameterType
异常提示:
-
stuNo不能使用,使用的是:【arg3,arg2,arg1,arg0,param3,param2,param1】
insert into empinfo(id,name,age,job,phone) values (#{arg0},#{arg1},#{arg2},#{arg3},#{arg4}) -
b. 命名参数的方式
可以在接口中通过@Param("")来指定sql中参数的名字
void insertEmpInfo(@Param("sId") String id, @Param("sName") String name, @Param("sAge") String age, @Param("sJob") String job, @Param("sPhone") String phone);
insert into empinfo(id,name,age,job,phone) values (#{sId},#{sName},#{sAge},#{sJob},#{sPhone}) -
c. 综合使用的情况
//一个是简单类型 ,一个是对象类型 void insertEmpInfo(@Param("sId") String id,@Param("empInfo") EmpInfo empInfo);
insert into empinfo(id,name,age,job,phone) values (#{sId},#{empInfo.name},#{empInfo.age},#{empInfo.job},#{empInfo.phone})
6.增加null
oracle:如果插入的 字段是null,提示错误:Other 而不是gnull
mysql:如果插入的字段是null,可以正常执行(没有约束)
原因:
各个数据库在Mybatis中对各种数据类型的默认值不一致。
mybatis中,jdbcTypeForNull(如果是null),则默认值OTHER。
在mysql中,mybatis将Other当做NULL来处理了,但是oracle不行。
解决:
oracle:null -> OTHER 手工告诉oracle:other -> null
a. 当某个数据类型oracle无法处理进,告诉它用默认值null 来处理
//使用#{empInfo.name,jdbcType=null}这个就可以了
insert into empinfo(id,name,age,job,phone)
values (#{sId},#{empInfo.name,jdbcType=null},#{empInfo.age},#{empInfo.job},#{empInfo.phone})
b. 配置mybatis全局配置文件conf.xml
7.返回值为HashMap的情况
- 注意:在mysql中@MapKey("id")字段为小写
- 在oracle中为全大写
- map:
- key:id value:Student
- 程序根据select的返回值,知道map的value就是EmpInfo,根据@MapKey("id")知道Map的key是id
@MapKey("id")
HashMap queryAllEmp();
8.ResultMap:字段和属性名的相应
- column指的是数据库中的列名
- property指的是类中的名字
9.别名问题
- 当这个包下的子包 与Student重名时,必须使用注解的方式重新命名
@Alias("myempinfo")
public class EmpInfo {
}
10.处理where子句后面的and的三种方式
- trim标签可以去掉后面的 and
可以处理拼接sql中【开头或结尾】第一个and
- prefix="where":在整个语句中加where
- prefix="set":在整个语句中加set,可用于更新
- prefixOverrides="and":智能处理前面的and
- suffixOverrides="and":智能处理后面的and
- suffixOverrides=",":智能处理后面的,常用于更新
and id = #{id}
and name like '%${name}%'
and phone = #{phone}
标签可以去掉前面的and
- 直接 在where后面加:1 = 1
11.内置参数
- _paramter:代表Mybatis的输入参数
- _databaseId:代表当前数据库的名字
12.模糊查询三种方式
12.1
- ${}原样输出
stuName like '%${stuName}%'
-
{}自动拼接' ':可以防止SQL注入
12.2 传值时,直接 传 %x%
student.setStuName("%s%");
stuName like #{stuName}
12.3 bind参数
and name like #{_queryName}
I:\MyBatisIdea\MyBatisGenerator\src\main\java
13.逆向工程
1.导入依赖
2.xml模板文件(修改生成路径、表名)
3.根据java模板类一键生成
- 根据学生表->学生类、学生Mapper接口、studentMapper.xml
4.如何使用
* 增加Mybatis配置文件 conf.xml
- 对于like模糊查询,逆向工程需要在传值时 写入%x%
逆向工程的实例:使用的是StudentExample
- 测试类
@Test
public void queryAllEmpById() throws Exception{
//Connection - SqlSession操作myBatis
//config.xml -> reader
Reader reader = Resources.getResourceAsReader("conf.xml");
//reader ->SqlSession
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
StudentExample example = new StudentExample();
StudentExample.Criteria criteria = example.createCriteria();
criteria.andStunameLike("%d%");
StudentExample example1 = new StudentExample();
StudentExample.Criteria criteria1 = example1.createCriteria();
//模糊查询
criteria1.andStunoEqualTo(10);
criteria1.andStunameLike("%k%");
//使用exampl整合的方式实现or操作
example.or(criteria1);
//Example中的Criteria:为查询的条件
List students = mapper.selectByExample(example);
System.out.println(students);
session.close();
}
14.MyBatis架构和源码解析
- Mybatis源码的几个主要部件
MyBatis中步骤:
- 1.获取SqlSessionFactory对象
- 2.获取SqlSession对象
- 3.获取xxxMapper对象(代理接口 中的方法、mapper.xml中的
- 4.执行标签中定义的SQL语句
1.获取SqlSessionFactory对象
- parse解析器
- 通过Configuration标签设置了properties、typeAliases、environments等
- 通过Configuration标签设置了properties、typeAliases、environments等
- Mybatis将所有的配置信息存放到了Configuration configuration对象中
- mapperElement的过程
- mapperElement的过程
-
- Mybatis会将xxxMapper.xml文件解析成MappedStatement对象
即parseStatementNode对象就是xxxMapper文件中的标签
MapperStatement -》存在于Configuration中
environment -》存在于Configuration中
-
所有的配置信息、增删改标签全部存在于Configuration中
SqlSessionFactory对象—》DefaultSqlSessionFactory—》Configuration—》所有的配置信息
2.获取SqlSession对象(Executor为执行器)
- configuration.newExecutor(tx, execType);-》默认类型为simpleExecutor
- 并且根据不同的类型execType,产生不同的Executor,并对执行器进行拦截操作:
executor = (Executor) interceptorChain.pluginAll(executor);
作用:以后如果我们要给MyBatis写自己的插件,就可以通过拦截器实现:
- 下图就是使用拦截器一次次增强执行器Executor,从而使Executor有更强大的功能!
返回的是:
DefaultSqlSession(configuration, executor, 事务问题);SqlSession ->openSession()--->openSessionFromDataSource() -->DefaultSqlSession对象
- 执行的流程
SqlSession -> DefaultSqlSession对象 -> 执行SQL
插件开发:
1.写插件
2.把插件放入到拦截器中插件
select * from student --》拦截器
目标对象target的包装后的产物 --->metaObject.getValue("可以从target中获取")
通过打印语句,可知,target就是 RoutingStatementHandler
----------》
metaObject.getValue("可以从RoutingStatementHandler中获取")
可以从RoutingStatementHandler获得:getBoundSql,getParameterHandler
------->--->metaObject.getValue("parameterHandler")
- metaObject.getValue("parameterHandler.parameterObject")//xxxMapper.xml中的语句中的参数值
- metaObject.getValue("parameterHandler.boundSql")//xxxMapper.xml中sql的语句