引言
MyBatis 的前身是 iBATIS , 是 Clinton Begin 在 2001 年发起的一个开源项目,最初侧重于密码软件的开发 , 后来发展成为一款基于 Java 的持久层框架。 2 004 年, C linton 将 iBATIS 的名字和源码捐赠给了 Apache 软件基金会,接下来的 6 年中,开源软件世界发生了巨大的变化, 一切开发实践、基础设施、许可,甚至数据库技术都彻底改变了 。 2010 年,核心开发团队决定离开 Apache 软件基金会,井且将 iBATIS 改名为 MyBatis oMyBatis 是一款优秀的支持自定义 SQL 查询、存储过程和高级映射的持久层框架,消除了几乎所有的 JDBC 代码和参数的手动设置以及结果集的检索 。 MyBatis 可以使用 XML 或注解进行配置和映射, MyBatis 通过将参数映射到配置的 S QL 形成最终执行的 S QL 语句 ,最后将执行SQL 的 结果映射成 Java 对象返回。与其他的 ORM (对象关系映射)框架不同, MyB atis 并没有将 Java 对象与数据库表关联起来,而是将 Java 方法与 SQL 语句关联。 MyBatis 允许用户充分利用数据库的各种功能,例如存储过程、视图、各种复杂的查询以及某数据库的专有特性 。如果要对遗留数据库、不规范的数据库进行操作 , 或者要完全控制 SQL 的执行, MyBatis 将会是一个不错的选择。与 JDBC 相比, MyBatis 简化 了相关代码, S QL 语句在一行代码中就能执行 。 MyBatis 提供了一个映射引擎 , 声明式地将 SQL 语句的执行结果与对象树映射起来。通过使用 一种内建的类XML 表达式语言, SQL 语句可以被动态生成。MyBatis 支持声明式数据缓存( declarative data caching ) 。当 一条 SQL 语句被标记为“可缓存”后,首次执行它时从数据库获取的所有数据会被存储在高速缓存中,后面再执行这条语句时就会从高速缓存中读取结果,而不是再次命中数据库 。 MyBatis 提供了默认情况下基于 Java HashMap 的缓存实现,以及用于与 OS Cache 、 Eh cache 、 Haze least 和 Memcached 连接的默认连接器,同时还提供了 API 供其他缓存实现使用。
1执行原理
l mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的 信息。
l mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。
l 通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。
l SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。
l Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括java的简单类型、HashMap集合对象、POJO对象类型。
1 准备数据库 ( mybaits )
CREATE TABLE `tb_employee` (
`emp_no` int(11) NOT NULL AUTO_INCREMENT,
`emp_name` varchar(50) DEFAULT NULL,
`emp_tel` varchar(50) DEFAULT NULL,
`emp_address` varchar(50) DEFAULT NULL,
PRIMARY KEY (`emp_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2 创建maven工程 ( 引入依赖 )
junit
junit
4.11
test
mysql
mysql-connector-java
5.1.46
org.mybatis
mybatis
3.4.5
3配置Mapper文件
配置 MyBatis 有多种方式,本节使用最基础最常用的 XML 形式进行配置 。
4配置 mybaits核心配置文件
5测试
@Test
public void test(){
try {
// 创建并获得 mybaits核心配置文件 的Reader流
Reader reader = Resources.getResourceAsReader("configer/mybatis.xml");
// 创建 SqlSessionFactory (回话工厂) 对象,需要一个Reader流
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 创建一个SqlSession (会话)
SqlSession session = sessionFactory.openSession();
// 查询数据
List
1、基础配置 说明
2、properties配置
使用
标签把数据库连接信息分离到 db.properties中单独维护
3、settingp配置
详细配置参考 http://www.mybatis.org/mybatis-3/zh/configuration.html#settings
4、typeAliases配置
类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
单个配置
包配置(推荐 ,别名就是简单类名)
注解配置( 前提必须开启 包别名配置 )
@Alias("Emp")
public class EmpModel {
}
这是一些为常见的 Java 类型内建的相应的类型别名。它们都是大小写不敏感的,需要注意的是由基本类型名称重复导致的特殊处理。
别名 映射的类型 _byte byte _long long _short short _int int _integer int _double double _float float _boolean boolean string String byte Byte long Long short Short int Integer integer Integer double Double float Float boolean Boolean date Date decimal BigDecimal bigdecimal BigDecimal object Object map Map hashmap HashMap list List arraylist ArrayList collection Collection iterator Iterator
标签:插入SQL语句
标签:修改SQL语句
标签:删除SQL语句
mybatis官方推荐的使用方式,使用Mapper接口调用Mapper XML 中的方法,该方法采用的是动态代理的方法,Mapper文件和 Dao接口绑定后,调用Dao接口(这里mybatis官方建议叫xxMapper 这只是一种风格)方法时,mybatis会自动创建Dao接口的实现类的代理对象(类似曾经的 xxxDaoImpl),该代理对象调用Mapper xml 文件中对应的方法。
定义Mapper接口
package com.xingxue.mybatis.dao;
import com.xingxue.mybatis.domain.EmpModel;
import java.util.List;
public interface EmpMapper {
public int add(EmpModel model) throws Exception;
public List list() throws Exception;
}
编写Mappper文件
insert into tb_employee(emp_no,emp_name,emp_tel,emp_address) values( #{empNo},#{empName},#{empTel},#{empAddress} );
测试
@Test
public void test(){
try {
// 创建并获得 mybaits核心配置文件 的Reader流
Reader reader = Resources.getResourceAsReader("configer/mybatis.xml");
// 创建 SqlSessionFactory (回话工厂) 对象,需要一个Reader流
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 创建一个SqlSession (会话)
SqlSession session = sessionFactory.openSession();
EmpMapper mapper = session.getMapper(EmpMapper.class);
//List list = mapper.list();
//System.out.println(list);
int row= mapper. add ( new EmpModel(108,"六六","北京","19939399") );
System.out.println("================="row+"====================");
session.commit();
session.close();
} catch (Exception e) {
e.printStackTrace();
}
}
MyBatis 的强大特性之一便是它的动态 SQL 。使用过 JDB C 或其他类似框架的人都会知道,根据不同条件拼接 SQL 语句时不仅不能忘了必要的空格,还要注意省略掉列名列表最后的逗号,处理方式麻烦且凌乱。 MyBatis 的动态 SQL 则能让我们摆脱这种痛苦。在 MyBatis 3 之前的版本中,使用动态 SQL 需要学习和了解非常多的标签,现在 MyBatis采用了功能强大的 OGNL ( Object-Graph Navigation Language )表达式语言消除了许多其他标签,以下是 MyBatis 的动态 SQL在 XML 中支持的几种标签。
if
choose (when 、 oterwise)
where 、 set
trim
foreach
bind (了解)
1 if 标签
查询
EmpModel md=new EmpModel();
md.setEmpNo(123);
//md.setEmpName("java");
// md.setEmpTel("188xx");
md.setEmpAddress("北京");
mapper.getEmpWithCondition(md);
==> Preparing: select * from tb_employee where 1=1 and emp_no=?
==> Parameters: 123(Integer)
<== Total: 0
更新
update tb_employee set
emp_name=#{empName},
emp_tel=#{empTel},
emp_address=#{empAddress},
emp_no=#{empNo}
where emp_no=#{empNo}
EmpModel md=new EmpModel();
md.setEmpNo(101);
md.setEmpName("java");
md.setEmpTel("188xx");
// md.setEmpAddress("北京");
mapper.updateWithModel(md);
==> Preparing: update tb_employee set emp_name=?, emp_tel=?, emp_no=? where emp_no=?
==> Parameters: java(String), 188xx(String), 101(Integer), 101(Integer)
<== Updates: 1
插入
insert into tb_employee(emp_no,emp_name
,emp_tel
,emp_address
)
values(
#{empNo},#{empName}
,#{empTel}
,#{empAddress}
)
EmpModel md=new EmpModel();
md.setEmpNo(404);
md.setEmpName("小张");
//md.setEmpTel("188xx");
md.setEmpAddress("北京");
mapper.insertWidthModel(md);
==> Preparing: insert into tb_employee(emp_no,emp_name ,emp_address ) values( ?,? ,? )
==> Parameters: 404(Integer), 小张(String), 北京(String)
<== Updates: 1
2 choose-when-therwise标签
EmpModel md=new EmpModel();
//md.setEmpNo(404);
md.setEmpName("小张");
mapper.getEmpByIdOrName(md);
==> Preparing: select * from tb_employee where emp_name=?
==> Parameters: 小张(String)
<== Columns: emp_no, emp_name, emp_tel, emp_address
<== Row: 404, 小张, null, 北京
<== Total: 1
3 where 标签
where 标签的作用:如果该标签包含的元素中有返回值,就插入一个 where ;如果 where后面的字符串是以 AND 和 OR 开头的,就将它们剔除。
EmpModel md=new EmpModel();
//md.setEmpNo(404);
//md.setEmpName("小张");
md.setEmpTel("188xx");
mapper.getEmpWithCondition(md);
<== Columns: emp_no, emp_name, emp_tel, emp_address
<== Row: 101, java, 188xx, 重庆
<== Total: 1
5 set标签
set 标签的作用:如果该标签包含的元素中有返回值,就插入一个 set :如果 set 后面的字符串是 以逗号结尾的,就将这个逗号剔除 。
update tb_employee
emp_name=#{empName},
emp_tel=#{empTel},
emp_address=#{empAddress},
where emp_no=#{empNo}
EmpModel md=new EmpModel();
md.setEmpNo(404);
md.setEmpName("小红");
md.setEmpTel("110");
//md.setEmpAddress("重庆");
mapper.updateWithModel(md);
==> Preparing: update tb_employee SET emp_name=?, emp_tel=? where emp_no=?
==> Parameters: 小红(String), 110(String), 404(Integer)
<== Updates: 1
6 trim标签
update tb_employee
emp_name=#{empName},
emp_tel=#{empTel},
emp_address=#{empAddress},
where emp_no=#{empNo}
7 foreach标签
delete from tb_employee where emp_no in
#{id}
List ids=new ArrayList<>();
ids.add(101);
ids.add(202);
ids.add(404);
mapper.deleteMany( ids );
==> Preparing: delete from tb_employee where emp_no in ( ? , ? , ? )
==> Parameters: 101(Integer), 202(Integer), 404(Integer)
<== Updates: 3
1 对 1 关联映射
:用于配置聚合属性 property:聚合属性
javaType:聚合和的类型【别名 或 全类名】
1 对 n 关系映射
n 对1关联映射:和1 对1 相同 使用 聚合属性
n 对n 关联映射 : 和 1 对n 相同使用 聚合集合
nb(牛逼) hashmap映射
public List
// 测试
SqlSession session = sqlSessionFactory.openSession();
EmpMapper mapper = session.getMapper(EmpMapper.class);
List
hashmap 映射就是不把数据映射到模型,而是映射到hashmap ,此处此种方法灵活,少配置
使用缓存可以使应用更快地获取数据,避免频繁的数据库交互 ,尤其是在查询越多 、缓存命中率越高的情况下,使用缓存的作用就越明显 。 MyBatis 作为持久化框架 , 提供了非常强大的查询缓存特性,可以非常方便地配置和定制使用 。一般提到 MyB atis 缓存 的时候,都是指二级缓存。 一级缓存( 也叫 本地缓存〉默认会启用,并且不能控制,因此很少会提到 。
mybatis一级缓存是 回话级别的缓存,也就是在同一个sqlsession 会话中的相同查询,会使用缓存数据,并不会在从新发送sql到数据库,除非缓存中没有数据才会重新发送sql重新查询。
缓存原理: MyBatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当 Map 缓存对象中己经存在该键值时,则会返回缓存中的对象。
mybaits一级缓存失效的集中情况:
第二次查询前 调用 session.clearCache()
两次查询 之间执行了更新操作 (INSERT UPDATE DELETE)
select 标签 flushCache="true"
session 关闭
mybatis 二级缓存是 namespace 空间级别的缓存,跟session 无关,即便在不同的session回话中,调用同一命名空间(namespace)下的方法做相同条件的查询,都可以使用到缓存数据。所以二级缓存是跨 session的。mybatis 默认是不启用二级缓存的,用户可以自行开启,同时还可以配置第三方的 缓存框架。
关于二级缓存,mybaits框架本身也有响应的实现,只是比较简单,通常开发中使用的第三方缓存技术包括
ehcache
memcached
redis
开启 mybatis的方法
mybatis.xml 主配置文件
mapper.xml 映射配置文件
映射语句文件中的所有 select 语句将会被缓存。
映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
model 实体类 实现序列化接口
public class GroupModel implements Serializable {
}
这里以ehcache为例,添加依赖
net.sf.ehcache
ehcache-core
2.6.8
org.mybatis.caches
mybatis-ehcache
1.1.0
ehcache.xml 核心配置文件( classpath下)
引用
org.mybatis.generator
mybatis-generator-maven-plugin
1.3.5
true
true
pageHeper是过国内的一个大神基于基于mybatis开发的一款分页插件,目前这个开源项目托管到GitHub上,项目地址https://github.com/pagehelper/Mybatis-PageHelper。
① Pom文件中添加依赖
com.github.pagehelper pagehelper 5.1.2
②mybaits配置文件中集成
详细参数设置参考:https://pagehelper.github.io/docs/howtouse/
③代码中使用
@Controller @Scope("prototype") public class StrutsAction extends ActionSupport { //依赖服务层 @Autowired private EmpService empService; public String hello(){ try { PageHelper.startPage(2,7,true); Listlist = empService.getAll(); //输出数据 for (TbEmployee emp :list){ System.out.println(emp); } //获得详细的分页信息 PageInfo pageInfo = new PageInfo<>(list); System.out.println(pageInfo); } catch (Exception e) { e.printStackTrace(); } return "hello"; } }