- MyBatis
- 基本介绍
- MyBatis开发(常规)
- MyBatis开发(接口)
- MyBatis开发(注解)
- MyBatis的基本架构
- MyBatis的作用域和生命周期
- 1. 作用域
- 2. SqlSessionFactory对象的自定义获取
- MyBatis的简单封装
- 核心配置文件Configuration.xml的几种元素
- ① properties
- ② Settings
- ③ typeAliases
- ④ Typehandlers
- ⑤ Plugins
- ⑥ Environments
- ⑦ databaseIdProvider
- ⑧ Mappers
- 核心映射文件Mappers.xml
- 1. 修改sql操作
- 2. 入参处理
- 3. Sql中的取值方式
- 4. 返回值类型的处理
- 5. select元素
- 6. 返回结果映射规则
- 级联关系-association
- 1. N-1
- 方式一:对象限定符
- 方式二:association赋值
- 方式三:分步查询
- 2. 1-N
- 方式一:collection元素进行赋值
- 方式二:分步查询
- 3. Discriminator鉴别器
- 动态sql
- 1. if
- 2. choose
- 3. where
- 4. trim
- 5. set
- 6. foreach
- 7. bind标签
- 8. Sql片段
- MyBatis内置参数
- 特殊字符处理
- MyBatis的缓存
- 一级缓存LocalCaching
- 二级缓存CachingExecutor
- 第三方缓存接口Ehcache
- SSM框架整合
- MBG
- MyBatis源码分析
Hibernate:全自动化的持久化(把内存中的瞬时数据永久的保存在磁盘上/数据库中的过程)框架
MyBatis:ORM 半自动化的持久化框架(SQL语句可以自己管理)
都是ORM (对象 关系 映射)框架
- O:javabean
- R:关系型数据库
- M:映射
① 下载地址
https://github.com/mybatis/mybatis-3/releases
https://github.com/mybatis/mybatis-3/releases/tag/mybatis-3.4.6
② 导入相应jar
③ 创建核心配置文件
在url后加上?useUnicode=true&characterEncoding=utf8是因为可能会出现字符集不匹配的问题
④ 创建实体映射bean
⑤ 创建sql映射文件(mapper文件)
⑥ 在核心配置文件中加载sql映射文件
⑦ 测试
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import bean.User;
public class Test {
public static void main(String[] args) {
String resource = "configuration.xml";
SqlSession session = null;
InputStream is = Test.class.getClassLoader().getResourceAsStream(resource);
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
session = ssf.openSession();
//User user1 = (User)session.selectOne("namespace1.selectUser", 1);
//接口方式
UserDao userdao = session.getMapper(UserDao.class);
User user2 = userdao.selectUser(1);
System.out.println(user2);
session.close();
}
}
⑧ 日志显示
① 创建接口和映射文件
- 映射文件的namespace和接口全路径一致 (让接口和映射文件进行动态绑定)
- 接口中抽象方法名、参数、返回值类型和映射文件中SQL的id、parameterType、resultType一致, (让接口方法和映射文件SQL进行动态绑定 )
② 核心配置文件中加载映射文件或接口
package dao;
import bean.User;
public interface UserDao {
public User selectUser(int uid);
}
③ 测试
mybatis通过接口方式是以Java动态代理模式进行实现的。
MyBatis开发(注解)① 无需创建xml映射文件
② 创建接口DAO,并在接口方法前通过@Select定义sql语句
“_name” --> @Param指定当前参数(sql中)的值
③ 在核心配置文件(configuration.xml)中加载接口
④ 测试
以接口的方式进行测试即可
MyBatis的基本架构 MyBatis的作用域和生命周期 1. 作用域●SqISessionFactoryBuilder
可以在任何时候被实例化、使用和销毁。一旦您创造 了SqISessionFactory就不需要再保留它
●SqlSessionFactory
SqlSessionFactory 一旦创建将会存在于您的应用程序整个运行生命周期中,不要在一个应用中多次创 建SqlSessionFactory
●SqISession
每个线程都有一个SqlSession 实例,SqlSession 实例是不被共享的,并且是线程不安全的作用域是request或者method
2. SqlSessionFactory对象的自定义获取import java.beans.PropertyVetoException;
import javax.sql.DataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import bean.User;
import dao.UserDao;
public class Test2 {
public static void main(String[] args) {
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("deve", transactionFactory, getDataSource());
Configuration config = new Configuration(environment);
//加载映射文件
config.addMapper(UserDao.class);
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
SqlSession session = ssf.openSession();
System.out.println("----------注解方式-------------");
UserDao userdao = session.getMapper(UserDao.class);
int i = userdao.selectUidByName("吴治峰");
System.out.println(i);
session.close();
}
private static DataSource getDataSource() {
ComboPooledDataSource ds = new ComboPooledDataSource();
try {
ds.setDriverClass("com.mysql.cj.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC");
ds.setUser("root");
ds.setPassword("123456");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return ds;
}
}
MyBatis的简单封装
package utils;
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class GetSqlSession {
public static SqlSession getSqlSession() {
String resource = "configuration.xml";
Reader reader = null;
try {
reader = Resources.getResourceAsReader(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = ssf.openSession();
return session;
}
}
核心配置文件Configuration.xml的几种元素
① properties
引入外部属性文件
② Settings设置或改变Mybatis运行过程中的行为方式
如上例子:mapUnderscoreToCamelCase选项开启,则开启驼峰命名映射,
如果数据库字段为A_NAME,则会映射为aName,首字母小写,去掉下划线,后面驼峰
③ typeAliases别名使用注意:
④ Typehandlers ⑤ Plugins ⑥ Environments ⑦ databaseIdProvider ⑧ Mappers 核心映射文件Mappers.xml 1. 修改sql操作public class Test4 {
public static void main(String[] args) {
String resource = "configuration.xml";
SqlSession session = GetSqlSession.getSqlSession(resource);
User user = new User(0,"张五","24",1);
UserDao userdao = session.getMapper(UserDao.class);
int i = userdao.insert(user);
if( i == 1) {
System.out.println("插入成功");
} else {
System.out.println("插入失败");
}
//session.commit();需要此函数才能提交到数据库
//或者SqlSession session = ssf.openSession(true);
//封装在了GetSqlSession.getSqlSession()里
session.close();
}
}
扩展:
插入数据时mybatis自动获取从数据库生成的主键(mysql自增长主键)方法:
解:java中对象之间支持值传递,不支持引用传递,即测试用例中的user和传过去的参数user指向同一块内存地址,如果在insert之后得到主键uid,可以改变这块内存地址user的主键, 再用getUid()便可以获取到。
设置useGeneratedKeys,允许JDBC支持自动生成主键,并在执行添加记录之后可以获取到数据库自动生成的主键ID。
设置keyProperty指定接受返回的属性,不指定的话也不会生成。
insert into usertable(name,age,sex) values(#{name},#{age},#{sex})
User user = new User(0,"张五","24",1);
UserDao userdao = session.getMapper(UserDao.class);
int i = userdao.insert(user);
if( i == 1) {
System.out.println("插入成功,uid为:" + user.getUid());
} else {
System.out.println("插入失败");
}
插入数据时获取插入的主键值(非自增长主键):
order设置为BEFORE表示先执行selectKey,在insert,AFTER相反,一般是BRFORE
rand()返回一个随机数,0~1。会有重复,这里仅演示,并不严谨。(后面的id是别名)
2. 入参处理参数处理方式
① 单个参数
MyBatis中可以接受基本类型以及对象类型的参数
基本类型:直接通过#{name}获取即可,name可自定义
对象类型:直接通过#{属性名}获取即可[建议]
Mybatis可以接受一个Map集合作为参数类型,sql中就可以通过获取map的key来得到参数值
② 多个参数
MyBatis可以接受任意多个参数
多个参数传入时都会被重新包装成一个Map,Map的key是arg0,arg1… 或者 param1,param2…,Map的值就是入参的值,在sql语句中获取Map的key从而得到参数的值
③ 命名参数
多个参数传入时,为了方便在sql中获取对于的参数值,从而可以在方法入参前指定sql中获取的参数名称
update usertable set age = #{Param1_age} where uid = #{Param1_uid}
public int updateParamAge(@Param("Param1_age")int age,@Param("Param1_uid")int uid);
入参处理源码分析
在调用接口处打上断点进行代码跟踪:
3. Sql中的取值方式① 两种方式:#{name}-通过Preparestatement的方式进行设置 ${name}-通过statement的方式进行设置
${}方式取值:
② mybatis对所有传入的NULL值映射的都是原生jdbc的OTHER类型(jdbcTypes.class文件中定义的枚举类型)
③ Mysql能够识别出OTHER类型,但是Oracle数据库则不能处理OTHER类型,可以在取值表达式中手动定义Null值得处理:*#{name,jdbcType=NULL}* 或者在核心配置文件
中设置全局null值处理,如下:
① Int/bean对象 对修改操作的返回值
② List 在sql映射文件中指定resultType的类型,此类型是List中的元素类型,mybatis会把查询结果中的每一条数据封装成一个resultType指定的类型并添加到List中
public ListselectParam(User user);
③ Map
A、返回单条记录:key就是列名,value为列的值,resultType=”map”/“Map”
public MapselectMapOne(int uid);
B、返回多条记录Map
@MapKey("name")//指定某个bean的属性值作为Map的key,这里指定的是name
public Map selectMap(int uid);
System.out.println("--------返回List---------");
User user = new User(5, "张%", "age", 1);
List list = userdao.selectParam(user);
for(User t :list) {
System.out.println(t);
}
System.out.println("--------返回Map(单条记录)---------");
Map map = userdao.selectMapOne(1);
for(Entry entry : map.entrySet()) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
System.out.println("--------返回Map(多条记录)---------");
Map map1 = userdao.selectMap(5);
for(Entry entry : map1.entrySet()) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
| 符号 | 转义字符 | 说明 |
|---|---|---|
| < | < | 小于 |
| <= | <= | 小于等于 |
| > | > | 大于 |
| >= | >= | 大于等于 |
| & | & | 逻辑与 |
| ‘xxx’ | ' | 单引号 |
| “xxx” | " | 双引号 |
① parameterType可省略,mybatis会根据TypeHandler.class and TypeHandlerRegistry.class进行自动匹配转换
② 元素属性
6. 返回结果映射规则① 可在全局setting中进行设置,实现的是自动映射
Setting的属性:默认是开启自动映射的功能,要求列名和属性名要一致,如果把值设为null,则取消自动映射
② 驼峰映射规则:A_COLUMN 自动映射成属性 aColumn,需要开启mapUnderscoreToCamelCase
③ 手动映射配置
① 在N端定义1端的对象属性
② 定义resultMap映射
③ Sql语句
方式二:association赋值
方式三:分步查询
① 创建1端的根据id查询对象的映射文件
② 在N端通过association元素进行映射
③ 延迟加载 | 懒加载
当开发者代码中调用哪个对象时才会向数据库发送sql请求
在全局配置文件中进行设置:
System.out.println("----------延迟加载/懒加载----");
User user3 = userdao.getUserN1_Step(1);
// System.out.println(user3);
//当直接输出对象时,因为address是它的属性,所以会立即加载
System.out.println(user3.getName());
//当输出的属性不涉及address时,延迟加载。
System.out.println(user3.getAddress());
2. 1-N
方式一:collection元素进行赋值
① 在1端的bean中创建接收N端的集合
② 在1端的映射文件中创建resultMap结果集的映射
方式二:分步查询
注意:映射文件中的sql元素需要和接口中的方法名要一致,mybatis是通过接口的动态代理去调用sql元素
懒加载策略和N-1中的一致
分步查询中传递多个参数:
把1端的多个元素作为查询的条件
延迟加载策略属性:
3. Discriminator鉴别器根据得到的某个参数值,不同的值/情况将会有不同的动作,其实就是if/else
动态sql动态sql可以灵活的根据业务逻辑条件自动组装最终执行的sql语句
OGNL:对象图导航语言,object.name
先附上测试:
public static void main(String[] args) {
String resource = "configuration.xml";
SqlSession session = GetSqlSession.getSqlSession(resource);
UserDao userDao = session.getMapper(UserDao.class);
User user = new User(0, "张%", "45", 1);
// System.out.println("----------动态sql:if/choose-----------");
// List userlist = userDao.getUser_if_choose(user);
// for(User u : userlist) {
// System.out.println(u);
// }
// System.out.println("----------动态sql:where/trim-----------");
// List userlist1 = userDao.getUser_where_trim(user);
// for(User u : userlist1) {
// System.out.println(u);
// }
// System.out.println("----------动态sql:set-----------");
// User user1 = new User(9, "王五", "45", 0);
// int i = userDao.updateUser_set(user1);
// System.out.println(i);
System.out.println("----------动态sql:foreach-----------");
List list = Arrays.asList(1,2,4,5,9);
List userlist2 = userDao.getUser_foreach(list);
for(User u : userlist2) {
System.out.println(u);
}
session.close();
}
1. if
test是条件,特殊字符用转义字符来写,&—>& “”
2. choose从多个选项中选择一个值,类似switch…case
子标签:when otherwise
3. where 4. trim
注意:prefix(加前缀),suffix(加后缀), prefixOverrides(去掉首个…),suffixOverrides(去掉最后的…)
5. setupdate usertable where uid = #{uid} name = #{name}, age = #{age},
使用trim替换set实现:
6. foreach接口中的参数可以是集合或数组类型,MyBatis会把参数自动的封装成Map对象,其中List对象的key是“list”,数组对象的key是”array”。
批量保存:
把某一个参数值绑定到上下文中的一个变量中,可以在sql中重复使用
8. Sql片段 MyBatis内置参数 特殊字符处理 MyBatis的缓存MyBatis中默认的缓存有两级缓存,分别是一级缓存和二级缓存
一级缓存LocalCaching与数据库在同一次会话期间所查询的数据会自动缓存到一级缓存中(本地缓存),如果后续对相同数据的查询,那么就会直接从本地缓存中进行获取,就不会再去查询数据库了。
String resource = "configuration.xml"; SqlSession session = GetSqlSession.getSqlSession(resource); //注意是同一个session UserDao userDao = session.getMapper(UserDao.class); //首次查询的结果会放入一级缓存中 User user = userDao.selectUser(1); System.out.println(user); //第二次查询相同的数据时就直接从以及缓存中获取 User user1 = userDao.selectUser(1); System.out.println(user1); System.out.println(user==user1); session.close();二级缓存CachingExecutor
① 二级缓存介绍
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import bean.User;
import dao.UserDao;
public class TestGlobalCache {
public static void main(String[] args) {
String resource = "configuration.xml";
Reader reader = null;
try {
reader = Resources.getResourceAsReader(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = ssf.openSession(true);
UserDao userDao = session.getMapper(UserDao.class);
//首次查询的结果放在一级缓存里
User user = userDao.selectUser(1);
System.out.println(user);
//关闭session,会把一级缓存里的内容转移到二级缓存里
session.close();
SqlSession session1 = ssf.openSession(true);
UserDao userDao1 = session1.getMapper(UserDao.class);
//查找: 先二级缓存,在一级缓存,最后DB
User user1 = userDao1.selectUser(1);
System.out.println(user1);
System.out.println(user==user1);//true
session1.close();
}
}
SqlSessionFactory要是同一个!!!
③ 二级缓存的运行过程
MyBatis主要是处理ORM的业务,并非专门做缓存处理的,MyBatis定义了Cache缓存接口方便开发者自定义缓存扩展,MyBatis官方提供了很多种集成缓存的Adapter适配器。
Ehcache是纯java写的缓存框架,是Hibernate中默认的缓存策略。
SSM框架整合SSM主要是指spring和mybatis的整合,spring和mybatis的整合需要在mybatis官网上下载mybatis-spring.jar整合包
① 创建web工程,引入ssm的jar
② 搭建Mybatis的环境
③ 搭建SpringMVC的环境
④ 搭建Spring的环境(Spring整合MyBatis的配置)
MBG MyBatis源码分析



