1.什么是MyBatis?
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的POJOs(Plan Old Java Objects,普通的 Java 对象)映射成数据库中的记录.
也称之为一个ORM(实体关系模型)框架,把数据库中的数据映射成程序中的实体,把程序中的实体映射成数据库中的数据。
2.步骤:
1. 导入MyBatis所需的Jar包,目前最新版本是3.4.4 ,上课所用的版本是3.2.8.建议大家不要去用最新版本,用以前一些旧的,比较成熟稳定的版本。而且以的我们的项目中所涉及到的框架比较的多,有时候会出现版本不兼容的情况。
2. 配置主配置文件:文件名建议用:mybatis-config.xml。
配置数据访问接口映射文件。文件名要与数据访问接口名一致。
3.主配置文件代码
<?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>
<!-- 外部属性文件导入,属性文件中通常配置数据库的连接信息 -->
<properties resource="config/conf.properties" />
<!-- <property name="driver" value="" />
<property name="url" value="" />
<property name="username" value="" />
<property name="password" value="" /> -->
<!-- 给每一个实体类去一个别名,建议别名和类名相同 -->
<typeAliases>
<!-- <typeAlias type="com.etc.dao" alias="User" /> -->
<!-- 把设定的包的类全部自动创建别名:创建的命名规则是:别名与类名相同 -->
<package name="com.etc.entity"/>
</typeAliases>
<!-- 对事务的管理和连接池的配置 -->
<environments default="development">
<!-- 定义开发环境 -->
<environment id="development">
<!-- 事务JDBC:由应用程序来管理事务,Managed:由系统来管理事务 -->
<transactionManager type="JDBC" />
<!-- 数据源类型是POOLED:表示使用连接池 UNPOOLED:表示不使用连接池 NDI在容器中来配置连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
<!-- 定义测试环境 -->
<environment id="test">
<!-- 事务JDBC:由应用程序来管理事务,Managed:由系统来管理事务 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源类型是POOLED:表示使用连接池 UNPOOLED:表示不使用连接池 NDI在容器中来配置连接池 -->
<dataSource type="POOLED">
<!-- config/conf.properties 属性文件中取连接数据库的信息 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
<!-- 定义运行环境 -->
<environment id="run">
<!-- 事务JDBC:由应用程序来管理事务,Managed:由系统来管理事务 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源类型是POOLED:表示使用连接池 UNPOOLED:表示不使用连接池 NDI在容器中来配置连接池 -->
<dataSource type="POOLED">
<!-- config/conf.properties 属性文件中取连接数据库的信息 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<!-- 映射数据访问接口的配置文件:注意,配置文件名与接口名要一致 -->
<mappers>
<!-- class:设置类名,url:引用某个路径下的接口文件 resource:直接指向映射文件 三种做法都不可取 -->
<!-- <mapper resource="/com/etc/dao/GradeDao.xml" /> -->
<!-- 把这个包中的所有映射文件全部进行扫描,注意:文件名一定要与接口名相同 -->
<package name="com.etc.dao"/>
</mappers>
</configuration>
4.映射文件配置
<?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">
<mapper namespace="com.etc.dao.SubjectDao">
<resultMap type="Subject" id="subjectResult">
<id column="subjectNo" property="subjectNo"/>
<result column="subjectName" property="subjectName"/>
<result column="classHour" property="classHour"/>
<association property="grade" column="gradeId" select="com.etc.dao.GradeDao.findById">
</association>
</resultMap>
<select id="find" resultMap="subjectResult">
select * from subject
</select>
<select id="search" resultMap="subjectResult" parameterType="Map">
select *from subject where 1=1
<!-- 动态SQL if test条件 -->
<if test="name!=null">
and subjectName like #{name}
</if>
<if test="hour!=null">
and classHour >=#{hour}
</if>
</select>
<select id="search1" resultMap="subjectResult" parameterType="Map">
select *from subject
<where><!-- 自动加上where 去掉第一个and -->
<!-- 动态SQL if test条件 -->
<if test="name!=null">
and subjectName like #{name}
</if>
<if test="hour!=null">
and classHour >=#{hour}
</if>
</where>
</select>
<select id="searchOrder" resultMap="subjectResult" parameterType="Map">
select * from subject
<choose>
<when test="name!=null">
order by subjectName
</when>
<when test="hour!=null">
order by classHour
</when>
<otherwise>
order by subjectNo
</otherwise>
</choose>
</select>
<select id="search2" resultMap="subjectResult" parameterType="Map">
select * from subject where subjectNo in
<!-- collection:集合对象 item:迭代出的值 separator:分隔符号 open:开始 close:关闭 -->
<foreach collection="list" item="id" separator=","
open="(" close=")">
#{id}
</foreach>
<!-- select * from subject where subjectNo in (2,5,4) -->
</select>
</mapper>
5.API,工厂的创建
package com.etc.util;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
//辅助类,创建SqlSession对象
public class SqlSessionFactoryUtil {
//读取MyBatis的主配置文件,形成一个文件流,注意:只需要读取一次文件就可以了
static SqlSessionFactory factory=null;
static InputStream is=null;
static{//用一个静态块读取主配置文件,获取返回的文件流。静态块在编译时就初始化
try {
is = Resources.getResourceAsStream("config/mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
}
//采用单例模式来保证工厂创建唯一
//这是懒汉式
public static SqlSessionFactory getSqlSessionFactory(){
if(factory==null){
//创建SqlSessionFactory工厂
factory =new SqlSessionFactoryBuilder().build(is);
}
return factory;
}
//获取SqlSession对象
public static SqlSession getSqlSession(){
return getSqlSessionFactory().openSession();
}
}
6.增删改
步骤:
1. 创建映射文件中对应的指令节点 ,并编写SQL语句
2. 执行指令,并必须提交事务.
3. 关闭SqlSession对象。
session=SqlSessionFactoryUtil.getSqlSession();
GradeDao dao=session.getMapper(GradeDao.class);
result=dao.add(grade);
session.commit();
return result;
7.查询
注意:查询不需要提交事务。
1. 创建映射文件中对应的指令节点,并编写SQL语句
2. 配置返回结果集resultMap
3. 关闭SqlSession对象。
增加:
获取主键的方法一:
<!-- parameterType:表示传入的类型 #{}:表示占位符 ? -->
<insert id="add" parameterType="Grade">
<!-- last_insert_id() 系统中的函数,能够获取最后产生的自动增长值 AFTER:表示执行之后再获取 -->
<selectKeykeyProperty="id" resultType="int"order="AFTER">
select last_insert_id()
</selectKey>
insert into gradevalues(null,#{gradeName})
</insert>
获取主键的方法二:
<!-- parameterType:表示传入的类型 #{}:表示占位符 ? -->
<insert id="add" parameterType="Grade"useGeneratedKeys="true" keyProperty="id">
insert into grade values(null,#{gradeName})
</insert>
SqlSession 自身也提供了数据操作方法:因为有类型转换问题及命名冲突的问题,所有不推荐使用,建议用映射文件数据访问接口来进行操作
Insert 增加
Update 修改
Delete 删除
selectOne 查询一个对象
selectList 查询多个对象
示例:
session.selectList("com.etc.dao.GradeDao.find");
参数1:保证Id的值的唯一性,如何不唯一,则一定要用全限定名。
8.分页查询
方法有两种,
1. MyBatis 自带的分页类: WorBounds,利用对象来实现分页功能,在查询时把这个类的对象作为参数传入,实现分页功能,但是这种方法性能上不是很好,如果表中的数据量大则不推荐使用。数据量少还是可用的。分页的机制是:把数据全部取出来之后 ,再进行分页。
//创建分页对象 参数1: 记录数的起始行,参数2:抓取记录数。
RowBounds rb = new RowBounds(0,3);
//带分页查询
returnsession.selectList("com.etc.dao.GradeDao.find",null,rb);
2. 基于SQL语句来实现分页 //parameterType=”Map”表示传入参数是一个Map对象 (<=#{gid} 是<=的意思)
1. 配置文件
<selectid="find" resultMap="gradeMap" parameterType="Map">
select * from grade where id <=#{gid} limit #{pageindex},#{pageSize}
</select>
2. 查询方法的封装。
//查询条件及分页数据的封装,封装成一个Map对象,并把Map对象传入映射文件中
int pageindex =1; //当前页
int pageSize = 3; //每页大小
Map<String,Object> map = newHashMap<String,Object>();
map.put("pageindex",(pageindex-1)*pageSize); //计算需要跳过多少条数据
map.put("pageSize",pageSize);
map.put("gid",5);
GradeDao dao =session.getMapper(GradeDao.class);
return dao.find(map); //调用方法取查询出来的分页数据。