MyBatis
2018-08-03 本文已影响0人
YasA
---------- Mybatis ------------
- web项目:
DBUtil(数据持久层) // 支持这两层的框架 hibernate、Mybatis
dao,entity,service(业务层) Model
servlet(控制器)
view(视图层)
(1).什么是Mybatis
- Mybatis最早源于Apache基金会的一个开源项目ibatis,2010年这个项目由ApacheSoftware foundation迁移到goole code
并且改名为mybatis。
- mybatis是支持普通sql查询,储存过程和高级映射的优秀持久层框架。
- mybatis封装了几乎所有的jdbc代码和参数的手工设置以及结果集检索。
- Mybatis使用简单的xml或者注解和定义映射关系,将java的pojos(实体类对象)映射成数据库中的记录。
(2).mybatis的体系结构
- mybatis体系结构有以下几个关键部分:
1.加载配置(有两种形式)
* xml配置文件
* java代码注解
(mybatis将sql的配置信息加载成为一个个的MappedStatement对象(传入参数映射配置、执行sql语句,结果映射配置))
并将其储存在内存中。
2.sql解析
* 当API接口层接收到调用请求的时候,会接收到传入sql的id和传入对象,mybatis会根据sql的id找到传入对象,
mybatis会根据sql的id找到对应的mappedstatement,然后根据传入参数对象对mappededstatement进行解析,
解析后可以得到最后要执行的sql语句和参数。
3.sql执行
* 将最终得到的sql和参数拿到数据库进行执行,得到操作数据库的结果。
4.结果映射配置
* 将操作数据库的结果按照映射配置进行转换,可以转换成HashMap、JavaBean或者基本数据类型等,并最终结果返回。
(3).Mybatis配置文件
- mybatis框架的xml配置文件包含下面两种类型:
1.sqlMapConfig.xml
* 主配置文件,用于指定数据库连接参数和框架参数的。
2.sqlMap.xml
* 映射定义文件,用于定义sql语句和映射信息。
(4).Mybatis框架API简介
- 在使用mybatis框架时,主要涉及以下几个API:
1.SqlSessionFactoryBuilder
* 该对象负责根据Mybatis配置文件SqlMapConfig.xml构建SqlSessionFactory实例。
2.SqlSessionFactory
* 每一个Mybatis的应用程序都以一个SqlSessionFactory对象为核心,该对象负责创建SqlSession对象实例。
3.SqlSession
* 该对象包含了所有执行sql操作的方法,用于执行已映射的sql。
(5).利用SqlSession实现crud操作
- 当获取SqlSession对象后,就可以利用它对数据库表执行增删改查的操作了。
使用步骤如下:
1.根据数据表编写实体类(java POJO)。
2.编写SqlMap.xml映射文件,定义sql操作和映射信息。
3.获取SqlSession对象,执行crud操作。
4.提交事务(DML操作)
5.释放SqlSession对象资源。
(6).解决实体类和表字段的对应问题
- Emp.xml
* resultMap:主要解决 实体类对应表字段不同名的问题 实体类属性对应表中字段
* property="属性"
* column="表中字段"
(7).利用mybatis实现分页查询(假分页)
缺点: mybatis 假分页(原理:实际是查询出所有记录,然后拿出部分,然后基于jdbc的absolute和next()方法获取部分记录)
如果数据庞大,使用假分页会出现内存异常。
- 在使用sqlSession的selectList()方法时,指定一个RowBounds分页器参数,即可指定返回的记录。
- RowBounds(offset,limit)构造器
- RowBounds bounds = new RowBounds(offset,limit); // offset:指定抓取记录的起始行,从0开始 limit
(8).Mapper映射器
- Mapper映射器是开发者创建绑定映射语句的接口,映射器接口实例可以从SqlSession中获取。
* SqlSession session = sqlSessionFactory.openSession();
* EmpMapper mapper = session.getMapper(EmpMapper.class);
-
1.创建web项目
action
dao
entity
util
2.lib导入jar包
mybatis-3.2.5.jar
mysql-connector-java-5.1.13-bin.jar
3.创建SqlMapConfig.xml 主配置文件(指定数据库连接参数和框架参数的)
/*
1.通过property标签关联数据库
2.配置实体类映射文件
*/
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
<configuration>
<environments default="environment">
<environment id="environment">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<!-- 主配置文件,用于指定数据库连接参数和框架参数的 -->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/db_emp" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 配置实体类映射文件 -->
<mappers>
<mapper resource="com/entity/Emp.xml"/>
</mappers>
</configuration>
4.util包下创建DBUtil关联SqlMapConfig.xml
package com.util;
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class DBUtil {
public static SqlSession getSession(){
// 加载配置文件
String conf = "SqlMapConfig.xml";
SqlSession session = null;
try {
// Resources.getResourceAsReader()读取配置文件
Reader reader = Resources.getResourceAsReader(conf);
// 根据Mybatis配置文件SqlMapConfig.xml构建SqlSessionFactory实例
SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
// 创建SqlSessionFactory 每一个Mybatis的应用程序都以一个SqlSessionFactory对象为核心,该对象负责创建SqlSession对象实例。
SqlSessionFactory sf = sfb.build(reader);
// 创建SqlSession对象 该对象包含了所有执行sql操作的方法,用于执行已映射的sql。
session = sf.openSession();
} catch (Exception e) {
e.printStackTrace();
}
return session;
}
//测试
public static void main(String[] args) {
SqlSession session = getSession();
System.out.println(session);
}
}
5.entity包下创建Emp实体类(关联表字段)
6.创建Emp.xml 映射定义文件(指定数据库连接参数和框架参数的)
<?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">
<!-- 映射定义文件,用于定义sql语句和映射信息 -->
<!-- 对应接口 -->
<mapper namespace="com.dao.EmpMapper">
<!--
属性:id="实现功能"
parameterType="传入参数类型" //id(int)
parameterMap(了解..)
resultType="返回类型"
resultMap="返回类型"
<insert></insert>: mybatis将sql的配置信息加载成为一个个的MappedStatement对象
-->
<!-- 实现EMP信息的添加功能 -->
<insert id="addEmp" parameterType="com.entity.Emp">
insert into
t_emp(name,sex,birthday,address,dept_id,aihao)
values(#{name},#{sex},#{birthday},#{address},#{dept_id},#{aihao})
</insert>
<!-- 实现EMP信息的修改功能 -->
<update id="updateEmp" parameterType="com.entity.Emp">
update t_emp set
name=#{name},sex=#{sex},birthday=#{birthday},address=#{address},dept_id=#{dept_id},aihao=#{aihao}
where id=#{id}
</update>
<!-- 实现EMP信息的删除功能 -->
<delete id="deleteEmp" parameterType="int">
delete from t_emp where
id=#{随便写}
</delete>
<!-- 实现EMP信息的查询功能 -->
<select id="findById" parameterType="int" resultMap="empMap">
select *
from t_emp where id=#{id}
</select>
<!-- 实现EMP信息的查询所有功能 -->
<select id="findAll" resultMap="empMap">
select * from t_emp
</select>
<!-- 查询员工信息列表 (真分页)-->
<select id="findPages" parameterType="com.entity.EmpPage" resultMap="empMap">
select * from t_emp limit #{page},#{pageSize};
</select>
<!--
resultMap:主要解决 实体类对应表字段不同名的问题 实体类属性对应表中字段
property="属性"
column="表中字段"
-->
<resultMap type="com.entity.Emp" id="empMap">
<result property="name" column="name" />
<result property="sex" column="sex" />
<result property="address" column="address" />
<result property="birthday" column="birthday" />
<result property="dept_id" column="dept_id" />
<result property="aihao" column="aihao" />
</resultMap>
</mapper>
8.创建EmpPage实体类(对应Emp.xml 真分页)
package com.entity;
public class EmpPage {
private int page;
private int pageSize;
// 对应xml #{page}
public int getPage() {
return (page-1)*pageSize;
}
public void setPage(int page) {
this.page = page;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}
7.dao包下创建EmpDao 实现功能(使用EmpMapper后,可以删除EmpDao)
package com.dao;
import java.util.List;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import com.entity.Emp;
import com.entity.EmpPage;
import com.util.DBUtil;
/**
* 1.获取工具类(static)
* 2.创建方法
* 3. 添加 session.insert("Emp.xml的id属性值",parameterType)
* 修改 session.update("Emp.xml的id属性值",parameterType);
* 删除 session.delete("Emp.xml的id属性值",parameterType);
* 查询单条数据session.selectOne("Emp.xml的id属性值",parameterType);
* 查询所有session.selectList("Emp.xml的id属性值"); // 查询所有不需要传入参数
*/
public class EmpDao {
// 获取工具类 session
static SqlSession session = DBUtil.getSession();
// 添加
public void saveEmp(Emp emp) {
// 根据session调用insert方法 ("对应xml里面的id值",对应实体类对象)
session.insert("addEmp", emp);
// 提交事务
session.commit();
// 释放资源
session.close();
}
// 修改
public void updateEmp(Emp emp) {
// 根据session调用update方法
session.update("updateEmp", emp);
// 提交事务
session.commit();
// 释放资源
session.close();
}
// 根据id删除
public void deleteEmp(int id) {
// 根据session调用delete方法
session.delete("deleteEmp", id);
// 提交事务
session.commit();
// 释放资源
session.close();
}
// 根据id查询
public Emp findEmpById(int id) {
// session.selectOne 查询并返回一条数据
Emp emp = session.selectOne("findById", id);
// 释放资源
session.close();
return emp;
}
// 查询员工列表
public List<Emp> findAll() {
List<Emp> emps = session.selectList("findAll");
// 释放资源
session.close();
return emps;
}
// 员工信息的分页查询(假分页)
public List<Emp> findPages(int page,int pageSize){
// 指定一个RowBounds分页器参数,指定返回的记录
RowBounds rb = new RowBounds((page-1)*pageSize, pageSize);
//
List<Emp> emps = session.selectList("findAll", null, rb);
// 释放资源
session.close();
return emps;
}
// 员工信息的分页查询(真分页)
public List<Emp> findPages2(EmpPage epage){
List<Emp> emps = session.selectList("findPages", epage);
session.close();
return emps;
}
// 测试
public static void main(String[] args) {
/*
// 添加
Emp emp = new Emp();
emp.setId(1);// 修改 需要id 添加不需要 id
emp.setName("Yazolo");
emp.setSex("1");
emp.setBirthday("1666-6-6");
emp.setAddress("休斯顿");
emp.setDept_id(2);
emp.setAihao("1,2");
EmpDao dao = new EmpDao();
// dao.saveEmp(emp);// 添加
dao.updateEmp(emp);// 修改
*/
/*
// 根据id删除
EmpDao dao = new EmpDao();
dao.deleteEmp(12);// 删除
*/
/*
// 根据id查询
EmpDao dao = new EmpDao();
Emp emp = dao.findEmpById(3);// 根据id查询
// 注:[如果xml查询配置字段不一样会报0(具体有解决方法 对应字段暂时解决这个问题)]
System.out.println(emp.getName() + "|" + emp.getSex() + "|"
+ emp.getBirthday() + "|" + emp.getAddress() + "|"
+ emp.getDept_id() + "|" + emp.getAihao());
*/
/*
// 查询所有
EmpDao dao = new EmpDao();
List<Emp> emps = dao.findAll();
System.out.println(emps.size() + "***********");
*/
/*
// mybatis 假分页(实际是查询出所有,然后拿出部分)
// 问题:如果数据庞大,使用假分页会出现内存异常。
EmpDao dao = new EmpDao();
List<Emp> emps = dao.findPages(1, 3);
for (Emp e : emps) {
System.out.println(e.getId()+"||"+e.getName());
}
*/
/*
// sql语句 分页
EmpDao dao = new EmpDao();
// 设置 page pageSize
EmpPage epage = new EmpPage();
epage.setPage(1);
epage.setPageSize(4);
List<Emp> emps = dao.findPages2(epage);
for (Emp e : emps) {
System.out.println(e.getId()+"||"+e.getName());
}
*/
}
}
9.创建接口 EmpMapper
/*
实现CRUD 分页... 功能
*/
package com.dao;
import java.util.List;
import com.entity.Emp;
import com.entity.EmpPage;
public interface EmpMapper {
/*
* 1.一个接口可以有多个方法
* 2.接口没有构造方法
* 3.接口里面所有方法必须是抽象(abstract)方法
* 4.接口不能包含成员变量,除了static和final变量
* 5.接口不是被类继承,而是要被类实现。
* 6.抽象类的方法可以有方法体,但接口中的方法不能有方法体
* 7.抽象类的成员变量可以是各种类型,而接口的成员变量只能是public static final类型
* 8.接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法
* 9.一个类只能继承一个抽象类,而一个类却可以实现多个接口。
* */
// 抽象方法是否传参取决于Emp.xml parameterType
// 添加员工信息
public void addEmp(Emp emp);
// 修改员工信息
public void updateEmp(Emp emp);
// 删除员工信息
public void deleteEmp(int id);
// 根据id查询
public void findById(int id);
// 查找所有员工
public List<Emp> findAll();
// 分页查询
public List<Emp> findPages(EmpPage epage);
}
10.创建测试类 EmpTest
package com.test;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.dao.EmpDao;
import com.dao.EmpMapper;
import com.entity.Emp;
import com.entity.EmpPage;
import com.util.DBUtil;
public class EmpTest {
public static void main(String[] args) {
// 获取工具类session
SqlSession session = DBUtil.getSession();
// 调用方法 得到Mapper接口
EmpMapper mapper = session.getMapper(EmpMapper.class);//(类类型)
/*
// 添加
Emp emp = new Emp();
emp.setName("IceIceIce...");
emp.setSex("0");
emp.setBirthday("1995-5-5");
emp.setAddress("菲律宾");
emp.setDept_id(2);
emp.setAihao("1,2");
mapper.addEmp(emp);
session.commit();
*/
/*
// 删除
mapper.deleteEmp(12);
session.commit();
*/
/*
// 修改
Emp emp = new Emp();
emp.setId(7);
emp.setName("Paparazi");
emp.setSex("1");
emp.setBirthday("1995-5-5");
emp.setAddress("上海");
emp.setDept_id(2);
emp.setAihao("1,2");
mapper.updateEmp(emp);
session.commit();
*/
/*
// 根据id查询
EmpDao dao = new EmpDao();
Emp emp = dao.findEmpById(5);
System.out.println(emp.getId()+"||"+emp.getName());
*/
/*
// 查询所有
List<Emp> emps = mapper.findAll();
for (Emp e : emps) {
System.out.println(e.getId()+"||"+e.getName());
}
*/
/*
// 分页查询
EmpPage epage = new EmpPage();
epage.setPage(1);
epage.setPageSize(3);
List<Emp> emps = mapper.findPages(epage);
for (Emp e : emps) {
System.out.println(e.getId()+"||"+e.getName());
}
*/
}
}