Mybatis
1. Mybatis是什么
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层(dao)框架。MyBatis 消除 了几乎所有的 JDBC 代码和 参数的手工设置 以及对 结果集的检索。MyBatis 可以使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java 对象)映射成数据库中的记录。
半orm(对象关系映射)框架。
Id name age
1 zhangsan 18
Student s = new Student(1,”zhangsan”,18);
Hibernate: orm框架;
session.save(s); session.update(s),session.delete(s);
Ibatis
2. 环境搭建
2.1 mybatis的配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <!-- 数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///mydb?unicode=true&characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="admin"/> </dataSource> </environment> </environments> <!-- 指定映射文件 --> <mappers> <mapper resource="com/itqf/domain/UsersMapper.xml"/> </mappers>
</configuration> |
2.2 编写映射文件
<?xml version="1.0" encoding="UTF-8"?> <!-- users的映射文件 --> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace="" 指定实体类的路径 --> <mapper namespace="com.itqf.domain.Users"> <!-- 查询 parameterType 参数类型 resultType 结果类型 #{id} :填充占位符 --> <select id="selectUsersById" parameterType="int" resultType="com.itqf.domain.Users" > select * from USERS where id=#{id} </select> <!-- 全查 List<Users> --> <select id="selectAllUsers" resultType="com.itqf.domain.Users"> select * from users </select> </mapper> |
2.3 测试
public class TestMybatis {
public static void main(String[] args) { //1,指定配置文件 5,通过sqlSession调用映射文件中的sql语句 Users u=new Users(); } |
3. 插入数据
3.1主键返回之自增主键
方法一:
方法二:
<insert id="saveUser" parameterType="com.itqf.domain.Users" useGeneratedKeys="true" keyColumn="id" keyProperty="id" > insert into users(uname,upass,sex,age) values(#{uname},#{upass},#{sex},#{age}) </insert> |
3.2主键返回值UUID
UUID函数是mysql的函数
Select UUID()
3.3主键返回值序列
oracle数据源的表的主键都是由序列管理(nextVal():序列的下一个值 )
序列也就是sequence,它是Oracle的主键生成策略
select seq.nextval from dual
dual :oracle的伪表
select 1+1 from dual;
4. mybatis开发dao的方式
1.1 需求
1、 根据ID查询Book信息
2、 根据名称模糊查询Book列表
3、 添加Book对象
1.2 原始dao的开发方式
即开发dao接口和dao实现类
1.2.1 Dao接口
1.2.2 Dao实现类
SqlSessionFactory,它的生命周期,应该是应用范围,全局范围只有一个工厂,使用单例模式来实现这个功能。与spring集成之后,由spring来对其进行单例管理。
SqlSession,它内部含有一块数据区域,存在线程不安全的问题,所以应该将sqlsession声明到方法内部。
1.2.3 测试代码
发现:代码冗余
5. Mapper代理的开发方式(重点)
即开发mapper接口(相当于dao接口)
Mapper代理使用的是jdk的代理策略(动态代理)。Proxy.newProxyInstance
源码中可查:
@SuppressWarnings("unchecked") protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } |
1.2.4 Mapper代理的开发规范
1、 mapper接口的全限定名要和mapper映射文件的namespace值一致。
2、 mapper接口的方法名称要和mapper映射文件的statement的id一致。
<select id=”findById”> statement
public Users findById();
3、 mapper接口的方法参数类型要和mapper映射文件的statement的parameterType的值一致,而且它的参数是一个。
4、 mapper接口的方法返回值类型要和mapper映射文件的statement的resultType的值一致。
Eg:
List<Book> findByBook(Book book); Mapper.xml: <select id=”findByBook” parameterType=”com.qf.domain.Book” resultType=”com.qf.domain.Book”>
|
1.2.5 mapper接口
1.2.6 mapper映射文件
在config下创建mapper目录然后创建UserMapper.xml(这是mybatis的命名规范,当然,也不是必须是这个名称)
sqlSession内部的数据区域本身就是一级缓存,是通过map来存储的。
Mapper文件的namespace需要和Mapper接口的接口名一致(全路径)
每个statement对象的id 与方法名一致。
1.2.7 加载映射文件
1.2.8 测试代码
SqlSession sqlSession = MybatisUtils.getSqlSession(); //得到代理对象 UsersMapper usersMapper = sqlSession.getMapper(UsersMapper.class); Users u = new Users(); u.setUname("刘诗诗"); u.setUpass("admin"); u.setSex("女"); u.setAge(18);
//usersMapper.save(u); |
6. 全局配置文件
1.3 概览
SqlMapConfig.xml的配置内容和顺序如下(顺序不能乱):dtd约束规定
Properties(属性)属性配置文件
Settings(全局参数设置) 懒加载 二级缓存
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件) 分页插件
environments(环境信息集合)
environment(单个环境信息)
transactionManager(事物)
dataSource(数据源)
mappers(映射器)
1.4 常用配置
1.4.1 Properties
SqlMapConfig.xml
加载的顺序
1、 先加载properties中property标签声明的属性
2、 再加载properties标签引入的java配置文件(properties配置文件)中的属性
3、 parameterType的值会和properties的属性值发生冲突。
<properties resource="dbinfo.properties"> <!-- <property name="driver" value="com.mysql.jdbc.Driver"/> --> </properties> |
1.4.2 settings
mybatis全局配置参数,全局参数将会影响mybatis的运行行为。
1.4.3 typeAliases
对po类进行别名的定义
1.4.3.1 mybatis支持的别名
别名 |
映射的类型 |
_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 |
1.4.3.2 自定义别名
<typeAliases> <!-- <typeAlias type="com.qf.domain.Book" alias="book"/> --> <!-- 批量别名定义(推荐) --> <!-- package:指定包名称来为该包下的po类声明别名,默认的别名就是类名(首字母大小写都可) --> <package name="com.qf.domain" /> </typeAliases> |
1.4.4 Mappers
1.4.4.1 <mapper resource=’’/>
使用相对于类路径的资源
如:<mapper resource=”book.xml” />
1.4.4.2 <mapper class=’’/>
使用mapper接口的全限定名
如:<mapper class="com.qf.mapper.BookMapper"/>
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
1.4.4.3 <package name=’’/>(推荐)
注册指定包下的所有映射文件
如:<package name="com.qf.mapper"/>
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下
映射文件
1.5 输入映射 parameterType
1.5.1 Pojo类型
参考入门程序之添加用户的映射文件
1.5.2 包装pojo类型
1.5.2.1 需求
高级查询时,根据图书书名、作者,类别查询
根据用户名 性别查询
1.5.2.2 创建包装pojo
1.5.2.3 映射文件
1.5.2.4 Mapper接口
1.5.2.5 测试代码
1.5.3 Map
同传递POJO对象一样,map的key相当于pojo的属性。
1.5.3.1 映射文件
<!-- 传递hashmap综合查询用户信息 -->
<select id="findBookByHashmap" parameterType="hashmap" resultType="user">
select * from book where id=#{id} and title like '%${title}%'
</select>
上边红色标注的是hashmap的key。
注意:
parameterMap="" 该属性已经过时了 不用 Caused by: java.lang.IllegalArgumentException: Parameter Maps collection does not contain value for com.itqf.dao.UsersMapper.map |
1.5.3.2 测试代码
Public void testFindBookByHashmap()throws Exception{ //获取session SqlSession session = sqlSessionFactory.openSession(); //获限mapper接口实例 BookMapper bookMapper = session.getMapper(BookMapper.class); //构造查询条件Hashmap对象 HashMap<String, Object> map = new HashMap<String, Object>(); map.put("id", 1); map.put("title", "科幻"); List<Book>list = bookMapper.findByHashmap(map); //关闭session session.close(); } |
1.6 输出映射
1.6.1 resultType
1.6.1.1 使用要求
使用resultType进行结果映射时,需要查询出的列名和映射的对象的属性名一致,才能映射成功。
如果查询的列名和对象的属性名全部不一致,那么映射的对象为空。
如果查询的列名和对象的属性名有一个一致,那么映射的对象不为空,但是只有映射正确那一个属性才有值。
如果查询的sql的列名有别名,那么这个别名就是和属性映射的列名。
1.6.1.2 简单类型
注意,对简单类型的结果映射也是有要求的,查询的列必须是一列,才能映射为简单类型。
1.6.2 resultMap
1.6.2.1 使用要求
使用resultMap进行结果映射时,不需要查询的列名和映射的属性名必须一致。但是需要声明一个resultMap节点,来对列名和属性名进行映射。(类似hibernate里面的映射文件<property>属性-à列对应关系 )
1.6.2.2 需求
对以下sql查询的结果集进行对象映射
Select id id_,title title,author author_from book where id = 1;
ResultType:结果集类型 可以是对象也可以是Map 实体类和数据库表的字段一致
ResultMap:结果集映射 ,当实体类属性与数据库字段(别名)不一致 需要做结果映射
ParameterType: 参数类型 可以是对象也可以是Map
ParameterMap:不用
1.6.3 动态sql
在mybatis中,它提供了一些动态sql标签,可以让程序员更快的进行mybatis的开发,这些动态sql可以通过sql的可重用性。。
常用的动态sql标签:if标签、where标签、sql片段、foreach标签
1.6.3.1 If标签/where标签
<select id="findBookAsResultMap" resultMap="myMap" parameterType="book1"> select title title1, author author1,publishdate publishdate1 from book <where> <if test="idList!=null and idList.size()!=0"> and bid in <!-- item="id" : 遍历的对象 定义的变量名 open="(" :遍历集合前拼接的字符串 close=")":遍历集合后拼接的字符串 separator:分隔符号 --> <foreach collection="idList" item="id" open="(" close=")" separator=","> #{id} </foreach> </if> </where> </select> |
1.6.3.2 Sql片段
Sql片段可以让代码有更高的可重用性
Sql片段需要先定义后使用
1.6.3.2.1需求
综合查询时,会根据ID集合进行查询
SELECT * FROM Book WHERE bid IN (1,5,10)
1.6.3.2.2修改包装pojo
1.6.3.2.3映射文件
1.6.3.2.4测试代码
面试题:
mybatis与hibernate的区别及各自应用场景
Mybatis技术特点:
1、 通过直接编写SQL语句,可以直接对SQL进行性能的优化;
2、 学习门槛低,学习成本低。
只要有SQL基础,就可以学习mybatis,而且很容易上手;
3、 由于直接编写SQL语句,所以灵活多变,代码维护性更好。
4、 不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。(分页:mysql limit, oracle:rownum)
Hibernate技术特点:
1、 标准的orm框架,程序员不需要编写SQL语句。
2、 具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
3、 学习门槛高,需要对数据关系模型有良好的基础(关联关系:一对一 一对多,多对多),而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
对应关系:一对多 一对一 多对多
4、 程序员不能自主的去进行SQL性能优化。
Mybatis应用场景:
需求多变的互联网项目,例如电商项目,金融类型,旅游类,售票类项目。
Hibernate应用场景:
需求明确、业务固定的项目,例如OA项目、ERP项目,CRM等。
重点:
ResultMap和ResultType的区别? 结果集映射
parameterType的用法?
Mybatis怎么获得自增主键?
Mybais的mapper开发方式?
Mybatis的动态sql?