MyBatis
MyBatis简介
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。 MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
MyBatis原理
原理:Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
MyBatis的框架核心
MyBatis配置文件,包括 Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息,映射文件配置了SQL执行相关的信息
MyBatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory(会话工厂)
通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。
SqlSession本身不能直接操作数据库,它是通过底层的Excutor执行器接口来操作数据库。
Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果映射信息。输入参数和输出结果的映射类型包括HashMap集合对象、POJO对象类型
Mybatis入门
下载MyBatis
下载地址:https://github.com/mybatis/mybatis-3/releases
导包
创建全局配置文件SqlMapConfig.xml
编写映射文件
在SqlMapConfig.xml中加载映射文件
编写测试程序
配置文件
<?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>
<!-- 配置mybatis的环境信息 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源,采用dbcp连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
</configuration>
- 映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
namespace:命名空间,它的作用就是对SQL进行分类化管理,可以理解为SQL隔离
注意:使用mapper代理开发时,namespace有特殊且重要的作用
-->
<mapper namespace="test">
<!--
[id]:statement的id,要求在命名空间内唯一
[parameterType]:入参的java类型
[resultType]:查询出的单条结果集对应的java类型
[#{}]: 表示一个占位符?
[#{id}]:表示该占位符待接收参数的名称为id。注意:如果参数为简单类型时,#{}里面的参数名称可以是任意定义
-->
<select id="findUserById" parameterType="int" resultType="com.gyf.domain.User">
SELECT * FROM USER WHERE id = #{id}
</select>
</mapper>
配置文件加载映射文件 在配置文件中添加<mappers>标签 子标签<mapper resource指定映射文件地址
测试程序
/读取配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
//通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
//通过SqlSessionFactory创建SqlSession
SqlSession session = ssf.openSession();
//调用SqlSession的操作数据库方法
User user = session.selectOne("findUserById",2);
//关闭sqlsession 释放资源
session.close();
查询案例
模糊查询
<!--
[${}]:表示拼接SQL字符串
[${value}]:表示要拼接的是简单类型参数。
注意:
1、如果参数为简单类型时,${}里面的参数名称必须为value
2、${}会引起SQL注入,一般情况下不推荐使用。但是有些场景必须使用${},比如order by ${colname}
-->
<select id="findUserByName" parameterType="String" resultType="com.gyf.domain.User">
SELECT * FROM USER WHERE username like '%${value}%'
</select>
- 查询
List<User> list = session.selectList("findUserByName","t");
插入
<insert id="insertUser" parameterType="com.xxx.xxx.User">
INSERT INTO USER(username,sex,birthday,address) VALUES(#{name},#{sex},#{birthday},#{address})
</insert>
session.insert("insertUser",new User(...));
session.commit();
删除
<delete id="deleteUser" parameterType="int">
DELETE FROM USER WHERE id=#{id}
</delete>
session.delete("deleteUser",1);
更新
<update id=“updateUser” parameterType="com.xxx.xxx.User">
Update From User SET username=#{username},sex=#{sex} WHERE id=#{id}
</update>
session.update("updateUser",user);
主键返回之MySQL自增主键
我们可以通过MySQL的函数获取到刚插入的自增主键
LAST_INSERT_ID()
<insert id="insertUser" parameterType="com.gyf.domain.User">
<!--
[selectKey标签]:通过select查询来生成主键
[keyProperty]:指定存放生成主键的属性
[resultType]:生成主键所对应的Java类型
[order]:指定该查询主键SQL语句的执行顺序,相对于insert语句
[last_insert_id]:MySQL的函数,要配合insert语句一起使用 -->
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
<!-- 如果主键的值是通过MySQL自增机制生成的,那么我们此处不需要再显示的给ID赋值 -->
INSERT INTO USER (username,sex,birthday,address)
VALUES(#{username},#{sex},#{birthday},#{address})
</insert>
主键返回之MySQL自增UUID
<selectKey keyProperty="id" resultType="String" order="BEFORE">
SELECT UUID()
</selectKey>
INSERT INTO USER (username,sex,birthday,address)
VALUES(#{username},#{sex},#{birthday},#{address})
</insert>
MyBatis使用Mapper接口代理方式 实现Dao
Mapper代理的开发模式,程序员只需要编写mapper接口(dao接口)。Mybatis会自动为mapper接口生成动态代理实现类
开发规范
mapper接口的全限定名要和mapper映射文件的namespace的值相同
mapper接口的方法名称要和mapper映射文件中的statement的id相同
mapper接口的方法参数只能有一个,且类型要和mapper映射文件中的statement的parameterType的值保持一致
mapper接口的返回值类型要和mapper映射文件中的statement的resultType值或resultMap中的type值保持一致
全局配置文件其他配置
properties数据库文件配置
Mybatis可以允许独立配置数据库文件
在src下配置个db.properties文件
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///mybatisdb
username=root
password=123456
修改Mybatis全局配置文件 sqlMapConfig.xml
<configuration>
<!-- 添加外部配置文件 -->
<properties resource="db.properties"/>
...
<dataSource type="POOLED">
<property name=driver value=#{driver} #配置文件中的配置名
</dataSource>
...以下代码省略
</configuration>
typeAliases 别名
别名是使用为了在映射文件中,更方便的去指定参数和结果集的类型,不用再写很长的全限定名
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 |
自定义别名
<configuration>
<!-- 指定自定义别名 -->
<typeAlias type="com.xxx.xxx.User" alias="user"/>
<!-- 批量设置别名-->
<!--[name]:指定批量定义别名的类包,别名为该包下的类名 -->
<package name="com.xxx.xxx"/>
</configuration>
mappers加载映射文件的几种方式
<mapper resource=""/>
<mapper url=""/> 几乎不用 完全限定路径
<mapper class=""/> 接口的类全限定名
Mybatis的映射文件
输入映射ParameterType
指定输入参数的Java类型,可以使用别名或者类的全限定名 可以接收 简单类型、POJO、对象、HashMap
输入映射resultType/resultMap
-
resultType
-
使用resultType结果进行映射时,查询的列名和映射的POJO属性名完全一致,该列才能映射成功
如果查询的列名和映射的pojo属性名全部不一致,则不会创建pojo对象
如果查询的列名和映射的pojo属性名有一个一致,就会创建pojo对象
-
-
输出简单类型
- 当输出结果只有一列时,可以使用ResultType指定简单类型作为输出结果类型
动态SQL
If和where
if标签
if标签 作为判断入参来使用,如果符合条件,则把if标签体内的SQL拼接上。
- UserMapper.xml
<select id="findGeneral" resultType="user">
SELECT * FROM tb_user WHERE 1=1
<if test="name !=null and name != ''">
AND name=#{name}
</if>
<if test="email !=null and email!=''">
AND email=#{email}
</if>
</select>
where标签
Where标签:会去掉条件中的第一个and符号
<select id="findGeneralwhere" resultType="user">
SELECT * FROM tb_user
<where>
<if test="name !=null and name !=''">
AND name=#{name}
</if>
<if test="email !=null and email !=''">
AND email=#{email}
</if>
</where>
</select>
choose标签
相当于java中的if...else if...else语句结构
sql = select * from user where 1=1
if( name != null ){
and name = #{}
}else if( email != null){
and email = #{}
}else{
and 1=2
}
- choose标签
<select id="findGeneralChoose" resultType="user">
SELECT * FROM tb_user
<where>
<choose>
<when test="name !=null and name!=''">
AND name = #{name}
</when>
<when test="email !=null and email!=''">
AND email=#{email}
</when>
<otherwise>
and 1=2
</otherwise>
</choose>
</where>
</select>
set用于update语句
<select id="updateGeneralSetUpdate" resultType="user">
UPDATE tb_user
<set>
<if test="name !=null and name!=''">
name = #{name},
</if>
<if test="email !=null and email!=''">
email=#{email},
</if>
</set>
where uid=#{uid}
</select>
SQL片段
Mybatis提供SQL片段的功能可以提高SQL的可重用性
SQL片段需要使用<sql id="片段名称">使用时 使用<include refid="片段名称">
foreach遍历
使用集合
<!--collection 表示参数的名称 如果是直接传入集合参数 此处只能填写[list|collection]-->
<!--item 每次遍历出来的对象-->
<!--open 开始遍历时拼接的串-->
<!--close 结束遍历时拼接的串-->
<!--separator 遍历出的每个对象之间需要拼接的字符-->
<select id="findByUserIds" resultType="user">
SELECT * FROM tb_user where uid IN
<foreach collection="collection" item="var" separator=","
open="(" close=")">
#{var}
</foreach>
</select>
使用数组
- 使用数组参数名称必须为array
<select id="findByUserIdsArr" resultType="user">
SELECT * FROM tb_user WHERE uid IN
<foreach collection="array" separator="," open="(" close=")" item="var">
#{var}
</foreach>
</select>
mybatis与hibernate的区别
Mybatis技术特点
- 好处
通过直接编写SQL语句,可以直接对SQL进行性能的优化;
学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
由于直接编写SQL语句,所以灵活多变,代码维护性更好。
- 缺点
不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
Mysql:limit
Oracle:rownum
需要编写结果映射。
Hibernate技术特点
- 好处
标准的orm框架,程序员不需要编写SQL语句。
具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
以后,mysql数据迁移到oracle,只需要改方言配置
- 缺点:
学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
程序员不能自主的去进行SQL性能优化。