一、什么是Mybatis
MyBatis是一个优秀的持久层框架,底层基于JDBC实现与数据库的交互。并在JDBC操作的基础上做了封装和优化,它借助灵活的SQL定制,参数及结果集的映射方式,更好的适应了当前互联网技术的发展。总之,Mybatis对JDBC访问数据库的过程进行了封装,简化了JDBC代码,解决JDBC将结果集封装为Java对象的麻烦。
二、使用JDBC编程和Mybatis编程的区别
1、使用传统方式JDBC访问数据库:
(1)使用JDBC访问数据库有大量重复代码(比如注册驱动、获取连接、获取传输器、释放资源等);
(2)JDBC自身没有连接池,会频繁的创建连接和关闭连接,效率低,耗内存;
(3)SQL是写死在程序中,一旦修改SQL,需要对类重新编译;
(4)对查询SQL执行后返回的ResultSet对象,需要手动处理,有时会特别麻烦
2、使用MyBatis框架访问数据库:
(1)Mybatis对JDBC对了封装,可以简化JDBC代码;
(2)Mybatis自身支持连接池(也可以配置其他的连接池),因此可以提高程序的效率;
(3)Mybatis是将SQL配置在mapper文件中,修改SQL只需要修改映射文件,类不需要重新编译。
(4)对查询SQL执行后返回的ResultSet对象,Mybatis会帮我们处理,转换成Java对象。
三、Mybatis编程步骤
(1)获取MyBatis核心配置文件/全局配置文件
(2)通过核心配置文件获取SqlSessionFactory工厂对象
(3)通过工厂对象打开SqlSession回话
(4)通过namespace+id找到要执行的sql语句并执行
(5)返回结果
public void findAll() throws IOException {
//1.读取mybatis的核心配置文件(mybatis-config.xml)
InputStream in = Resources
.getResourceAsStream("mybatis-config.xml");
//2.通过配置信息获取一个SqlSessionFactory工厂对象
SqlSessionFactory fac = new SqlSessionFactoryBuilder().build( in );
//3.通过工厂(SqlSessionFactory)打开Session
SqlSession session = fac.openSession();
//4.通过[namespace+id]找到要执行的sql语句并执行sql语句
List<Emp> list = session.selectList("EmpMapper.findAll");
//5.输出结果
for(Emp e : list) {
System.out.println( e );
}
}
1)在编写之前的准备
(1)创建一个maven工程
(2)在pom.xml文件中导入所需要的依赖
(3)创建核心配置文件(mybatis-config.xml)和映射文件(EmpMapper.xml)
(4)在核心配置文件中配置环境(事务管理方式--JDBC/MANAGED和数据源--POOLED/UNPOOLED),和导入映射文件
(5)编写实体类(Emp.java),用于封装数据,实体类中的属性和数据库表中的列名尽量保持一致,添加私有属性提供对应的get和set方法,并重写toString方法
注意:在写映射文件的时候Mapper标签上的namespace,要求不能重,select/insert/update/delete 标签上的id属性也不能重复,在程序中通过【namespace + id 】定位到要执行哪一条SQL语句
2)如果实体类的属性与数据库表中的字段(列名)不一致的解决方法
(1)在为字段添加别名
假如Emp的属性值为 idd,namee ,jobb,salary --- 数据库表中的列名为id,name,job,salary
<select id="findAll" resultType="com.tedu.pojo.Emp">
select id idd,name namee,job jobb,salary from Emp
</select>
(2)使用sql标签,也是添加别名,只是把它提取到了sql标签
<!-- id属性为唯一标识,与refid相对应 -->
<sql id="emp">
id idd,
name namee,
job jobb,
salary salary
</sql>
<select id="findAll" resultType="com.tedu.pojo.Emp">
select
<include refid="emp"/>
from Emp
</select>
(3)使用resultMap标签
type 属性:用于指定将数据的返回结果封装到哪个实体类中
id属性: 这个封装规则的唯一标识,用于被查询标签中的resultMap所引用
colunm属性:填写数据库表的字段名
property属性:填写实体类的属性值
如果数据库表中的字段名与实体类属性相同的可以不写
<resultMap type="com.tedu.pojo.Emp" id="empMap">
<!-- 如果是主键需要用id标签,其他的除集合外用result标签存储数据库字段与实体类之间的映射 -->
<id column="id" property="idd"/>
<result column="name" property="namee"/>
<result column="job" property="jobb"/>
</resultMap>
<select id="findAll" resultMap="empMap">
select * from Emp
</select>
四、Mybatis中#{}和${}的区别
#{}:相当于JDBC中的问号(?)占位符,会先预编译,能防止SQL注入攻击,并且当#{}占位符是为字符串或者日期类型的值进行占位时,会进行转义处理(在字符串或日期类型的值的两边加上单引号);
${}:是为SQL片段进行占位,直接将传过来的SQL片段拼接在 ${} 占位符所在的位置,不会进行任何的转义处理。由于是直接将参数拼接在SQL语句中,因此可能会引发SQL注入攻击问题
需要注意的是:使用 ${} 占位符为SQL语句中的片段占位时,即使只有一个占位符,需要传的也只有一个参数,也需要将参数先封装再传递!
<!-- $占位符进行模糊查询 -->
select * from emp where name like '%${name}%'
<!-- #占位符使用concat函数进行字符串拼接 能防止sql注入 -->
select * from emp where name like concat('%',#{name},'%')
五、MyBatis的动态SQL标签
(1)where标签
用于对包含在其中的SQL片段进行检索,在需要时可以生成where关键字,并且在需要时会剔除多余的连接词(比如and或者or)
(2)if标签
是根据test属性中的布尔表达式的值,从而决定是否执行包含在其中的SQL片段。如果判断结果为true,则执行其中的SQL片段;如果结果为false,则不执行其中的SQL片段
<select id="select01" resultType="com.tedu.pojo.Emp">
select * from emp
<where>
<if test="name != null">
and name = #{name}
</if>
<if test="salary!= null">
and salary = #{salary}
</if>
</where>
</select>
(3)choose标签
按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行 otherwise中的sql。类似于Java 的switch case语句,choose为switch,when为case,otherwise则为default。
<select id="select01" resultType="com.tedu.pojo.Emp">
select * from emp
<where>
<choose>
<when test="name!=null ">
and name = #{name}
</when>
<when test="job!= null ">
and job =#{job}
</when>
<otherwise>
and id = 10
</otherwise>
</choose>
</where>
</select>
(4)set标签
使用set标签可以将动态的配置set关键字,和剔除追加到条件末尾的任何不相关的逗号。
<update id="update01" resultType="com.tedu.pojo.Emp">
update emp
<set>
<if test="name!=null ">
name =#{name},
</if>
<if test="job!=null ">
Job =#{job},
</if>
<if test="salary!=null ">
salary = #{salary}
</if>
</set>
where id =#{id}
</update>
(5)foreach标签
可以对传过来的参数数组或集合进行遍历。以下是它的一些基本属性:
item必需,若collection为数组或List集合时,item表示其中的元素,若collection为map中的key,item表示map中value(集合或数组)中的元素
collection必需,值为遍历的集合类型,例如:如果参数只是一个数组或List集合,则collection的值为array或list;如果传的是多个参数,用map封装,collection则指定为map中的key。
open可选,表示遍历生成的SQL片段以什么开始,最常用的是左括号'('
close可选,表示遍历生成的SQL片段以什么结束,最常用的是右括号')'
separator可选,每次遍历后给生成的SQL片段后面指定间隔符
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="array" open="(" item="id" separator="," close=")">
#{id}
</foreach>
</delete>
六、MyBatis的接口开发
(1)创建一个接口,接口的全限定类名和mapper文件的namespace值要相同
(2)mapper文件中每条要执行的SQL语句,在接口中要添加一个对应的方法,并且接口中的方法名和SQL标签上的id值相同
(3)Mapper接口中方法接收的参数类型,和mapper.xml中定义的sql的接收的参数类型要相同
(4)接口中方法的返回值类型和SQL标签上的resultType即返回值类型相同(如果方法返回值是集合,resultType只需要指定集合中的泛型)
测试类的实现代码
public void testFindById() throws Exception{
//1、获取核心配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml")
//2、获取工厂对象,并根据工厂对象获取SqlSession对象
SqlSessionFactory fac =new SqlSessionFactoryBuilder().build(in);
//true表示自动提交事务,mabatis默认手动提交
SqlSession session = fac.openSession(true);
//3.获取Mapper接口对象
EmpMapper map = session.getMapper(EmpMapper.class);
//4.调用接口对象的方法进行查询
Emp e = map.findById(2);
//5.输出结果
System.out.println(e);
}