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());
        }
        */
    }
}

上一篇下一篇

猜你喜欢

热点阅读