mybatis

  1. 云栖社区>
  2. 博客>
  3. 正文

mybatis

我巴巴 2018-10-06 20:36:48 浏览988
展开阅读全文

一、什么是mybatis

  MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。 MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及对结果集的检索。 MyBatis 可以使用简单的XML 或注解用于配置和原始映射,将接口和 Java 的 POJO( Plain Old Java Objects,普通的Java 对象)映射成数据库中的记录。

二、开发实例基本步骤:

1. 官网下载mybatis的jar包及源码包。

  https://github.com/mybatis/mybatis-3/releases

2. Eclispe创建maven工程。

_HUK_E9QRP_6SZ3_CXB4YCT

3. 在pom文件引入一些相关的jar包。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mybatis</groupId>
  <artifactId>mybatisdemo</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>

  <name>mybatisdemo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <!-- 测试依赖jar包 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- mysql驱动依赖jar包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!-- mybatis依赖jar包 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!-- 日志相关jar包 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!-- 分页插件 -->
        <dependency>
             <groupId>com.github.pagehelper</groupId>
             <artifactId>pagehelper</artifactId>
             <version>4.1.4</version>
         </dependency>
  </dependencies>
  <build>
      <plugins>
          <!-- maven编译插件 设置工程jdk编译版本,默认是1.5 -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.1</version>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
      </plugins>
  </build>
</project>

4. 新建resources资源文件夹,引入log4j配置文件。

log4j.properties:

#在开发环境下日志级别要设置成debug,生产环境设置成info或error
log4j.rootLogger=debug, stdout 
log4j.logger.com.mybatis.myb.dao =TRACE
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
log4j.appender.stdout.encoding=utf-8

5. 编写mybatis配置文件 参考资料: http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

db.properties:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/yccz?characterEncoding=utf8
jdbc.username=root
jdbc.password=mysql

mybatis-config.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>

    <!-- 加载属性文件 -->
    <properties resource="db.properties">
        <!--properties中还可以配置一些属性名和属性值  -->
        <!-- <property name="jdbc.driver" value=""/> -->
    </properties>
    
    <settings>
        <!-- 打开延迟加载的开关 -->
        <setting name="lazyLoadingEnabled" value="false"/>
        <!-- 将积极加载改为消极加载即按需要加载-->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
    
    <!-- 针对单个别名定义,type:类型的路径,alias:别名 -->
    <!--<typeAliases>
              <typeAlias alias="Area" type="com.yc.yd.model.Area"/>
    </typeAliases -->
    <!-- 
        包扫描方式配置别名 
        指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)
    -->
    <typeAliases>
      <package name="com.mybatis.myb.model"/>
    </typeAliases>
    
    <!-- 分页插件 -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <property name="dialect" value="mysql"/>
            <property name="rowBoundsWithCount" value="false"/> 
        </plugin>
    </plugins>
    
    <!-- 环境配置 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理,事务控制由mybatis-->
            <transactionManager type="JDBC"/>
            <!-- 数据库连接池,由mybatis管理-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>
</configuration>

6. 编写数据库中对应的JavaBean类

package com.mybatis.myb.model;

import java.util.Date;

public class ClassBean{
    
    private Integer classId;
    private String className;
    
    private Date classTime;
    private String classRoom;
    
    private TeacherBean teacher;
    
    public Integer getClassId() {
        return classId;
    }
    public void setClassId(Integer classId) {
        this.classId = classId;
    }
    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
    public Date getClassTime() {
        return classTime;
    }
    public void setClassTime(Date classTime) {
        this.classTime = classTime;
    }
    public String getClassRoom() {
        return classRoom;
    }
    public void setClassRoom(String classRoom) {
        this.classRoom = classRoom;
    }
    public TeacherBean getTeacher() {
        return teacher;
    }
    public void setTeacher(TeacherBean teacher) {
        this.teacher = teacher;
    }
}
package com.mybatis.myb.model;

public class TeacherBean {
        private Integer tId;
        private String cTeacher;
        private Integer type;
        public Integer gettId() {
            return tId;
        }
        public void settId(Integer tId) {
            this.tId = tId;
        }
        public String getcTeacher() {
            return cTeacher;
        }
        public void setcTeacher(String cTeacher) {
            this.cTeacher = cTeacher;
        }
        public Integer getType() {
            return type;
        }
        public void setType(Integer type) {
            this.type = type;
        }
}

7. 编写Mapper接口

package com.mybatis.myb.dao;

import java.util.List;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import com.mybatis.myb.model.ClassBean;

public interface ClassDao {
    public List<ClassBean> queryClass(ClassBean vo);
    
    public int insertclass(ClassBean vo);
    //数据库语句写在注解里面,就不用再在xml文件里面配置了,不推荐这种方式
    @Select("select * from t_class where classid=#{a} and classname=#{b}")
    public List<ClassBean> queryClassByVo(@Param("a")int classid,@Param("b")String classname);
    
    public List<ClassBean> queryInfoByIds(@Param("list")List<ClassBean> list);
    
    public List<ClassBean> queryInfoByIdsaa(@Param("ids")String ids);
    
    
    public List<ClassBean> selectAll();
    
    public List<ClassBean> selectByClass();
    
}

8. 编写MapperXML文件

<?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.mybatis.myb.dao.ClassDao">
<!-- result:配置表字段(column)与类属性(property)的映射关系 -->
    <resultMap type="ClassBean" id="classselect">
        <result column="classid" property="classId"/>
        <result column="classname" property="className"/>
        <result column="class_time" property="classTime"/>
        <result column="class_room" property="classRoom"/>
        <!-- 一对一的JavaBean属性可以直接用 “.”来映射 类属性.JavaBean属性 -->
        <result column="teaid" property="teacher.tId"/>
        <result column="c_name" property="teacher.cTeacher"/>
        <result column="c_type" property="teacher.type"/>
    </resultMap>
    
    
    <resultMap type="ClassBean" id="classselect1">
        <id column="classid" property="classId"/>
        <result column="classname" property="className"/>
        <result column="class_time" property="classTime"/>
        <result column="class_room" property="classRoom"/>
        <!--  association:一个复杂类型的关联;许多结果将包装成这种类型 -->
        <!-- javaType:一个 Java 类的完全限定名,或一个类型别名 -->
        <association property="teacher" javaType="TeacherBean">
            <id column="teaid" property="tId"/>
            <result column="c_name" property="cTeacher"/>
            <result column="c_type" property="type"/>
        </association>
    </resultMap>
    
    <resultMap type="ClassBean" id="classselect2">
        <id column="classid" property="classId"/>
        <result column="classname" property="className"/>
        <result column="class_time" property="classTime"/>
        <result column="class_room" property="classRoom"/>
        <!-- column:关联查询时 主表关联的外键  -->
        <!-- select:另外一个映射语句的 ID,可以加载这个属性映射需要的复杂类型。获取的 在列属性中指定的列的值将被传递给目标 select 语句作为参数。
        注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。 -->
        <association property="teacher" column="t_id" select="selectTeacherid"/>
        <!-- 这种查询把一对一查询分成了两条查询语句 -->
    </resultMap>
    <resultMap type="TeacherBean" id="selectTeacher4">
            <id column="t_id" property="tId"/>
            <result column="c_name" property="cTeacher"/>
            <result column="c_type" property="type"/>
    </resultMap>
    <!-- resultMap:声明查询结果的映射结果集 -->
    <select id = "selectByClass" resultMap = "classselect2">
        select * from t_class
    </select>
    <!-- #{属性名} 可以把属性的值作为查询条件的值传给数据库语句-->
    <!-- 这里的id必须和接口的方法名一致才能映射上 -->
    <select id = "selectTeacherid" resultMap = "selectTeacher4">
        select * from t_teacher where t_id=#{tId}
    </select>
    
    <select id="selectAll" resultMap="classselect1">
        SELECT c.*,t.t_id as teaid,t.c_name,t.c_type FROM t_class c
        inner JOIN t_teacher t ON c.t_id=t.t_id
    </select>
    <!-- sql标签可以用来包含数据库语句段,如果一段数据库语句使用频率较高,就可以用这个标签包起来,要用着段语句的时候只要引用标签id即可 -->
    <sql id="selid">
        SELECT * FROM t_class
    </sql>
    <select id = "queryClass" resultMap="classselect">
        <!-- 引用数据库语句段 -->
        <include refid="selid"/>
        <where>
            <!-- 通过判断字段是否为空来决定是否加入条件,也就是可选条件 -->
            <!-- 注意:mybatis没有else标签 -->
            <if test="classTeacher!=null and classTeacher !=''">
                and class_teacher=#{classTeacher}
            </if>
            <!--     #and classname like concat('%',#{className},'%') -->
            <if test = "className != null and className !=''">
                and classname like '%${className}%'
            </if>
        </where>
    </select>
    <update id="updateclass">
        update t_class
        <!-- set 元素会动态前置 SET 关键字,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号。  -->
        <set>
            <if test="className!=null and className !=''">
                classname=#{className},
            </if>
            <if test="classTeacher != null and classTeacher != ''">
                class_teacher=#{classTeacher},
            </if>
        </set>
    </update>
    <select id = "queryClasscount" resultType="int">
        SELECT count(1) as count FROM t_class
        where class_teacher=#{classTeacher}
    </select>
    <!-- useGeneratedKeys:(仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。 -->
    <!-- keyProperty:(仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 -->
    <!-- keyColumn:(仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 -->
    <insert id="insertclass" useGeneratedKeys="true" keyProperty="classId" keyColumn="classid">
        insert into t_class(classname,class_teacher,class_time,class_room)
        values(#{className},#{classTeacher},now(),#{classRoom})
    </insert>
    
    <!-- resultType:将resultType指定为map,表示返回值类型为Map,用于查询非实体对象的情况,如统计查询。 -->
    <select id="queryInfoByIds" resultMap="classselect">
        <include refid="selid"/>
         WHERE classid in
         <!-- foreach 可以遍历一个集合,你可以指定元素体内的集合项、索引变量、开闭匹配的字符串以及在迭代中间放置分隔符。  -->
        <foreach item="a" index="index" 
              collection="list" open="(" separator="," close=")">  
              #{a.classId} 
        </foreach>
    </select>
    <select id="queryInfoByIdsaa" resultMap="classselect">
        <include refid="selid"/>
         WHERE classid in(${ids})
    </select>
    
    <delete id ="del">
        delete from t_class where classid in(${ids})
    </delete>
    <!-- #{}和${} 的区别是#{}会把传过来的值当字符串,会加上引号,${}会把传过来的值直接去拼接数据库语句,不会加引号,除非需要,否则一般情况都会用#{}-->
</mapper>

9. 在mybatis配置文件中注册MapperXML文件

在配置文件中加上:

<!-- mapper.xml配置 -->
    <mappers>
        <mapper resource="com/mybatis/myb/mapper/classmapper.xml"/>
    </mappers>

添加后的mybatis-config.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>

    <!-- 加载属性文件 -->
    <properties resource="db.properties">
        <!--properties中还可以配置一些属性名和属性值  -->
        <!-- <property name="jdbc.driver" value=""/> -->
    </properties>
    
    <settings>
        <!-- 打开延迟加载的开关 -->
        <setting name="lazyLoadingEnabled" value="false"/>
        <!-- 将积极加载改为消极加载即按需要加载-->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
    
    <!-- 针对单个别名定义,type:类型的路径,alias:别名 -->
    <!--<typeAliases>
              <typeAlias alias="Area" type="com.yc.yd.model.Area"/>
    </typeAliases -->
    <!-- 
        包扫描方式配置别名 
        指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)
    -->
    <typeAliases>
      <package name="com.mybatis.myb.model"/>
    </typeAliases>
    
    <!-- 分页插件 -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <property name="dialect" value="mysql"/>
            <property name="rowBoundsWithCount" value="false"/> 
        </plugin>
    </plugins>
    
    <!-- 环境配置 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理,事务控制由mybatis-->
            <transactionManager type="JDBC"/>
            <!-- 数据库连接池,由mybatis管理-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>
    <!-- mapper.xml配置 -->
    <mappers>
        <!--通过resource方法一次加载一个映射文件 -->
        <!-- 通过mapper接口加载单个 映射文件
        遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
        上边规范的前提是:使用的是mapper代理方法
         -->
        <mapper resource="com/mybatis/myb/mapper/classmapper.xml"/>
        <!-- 批量加载mapper
        指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载
        遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
        上边规范的前提是:使用的是mapper代理方法
         -->
        <!-- <package name="cn.itcast.mybatis.mapper"/> -->
    </mappers>
    
</configuration>

10. 编写一个SqlSessionFactory及SqlSession获取工具类

11. 编写一个测试类

package com.mybatis.myb.dao;

import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.mybatis.myb.model.ClassBean;

public class ClassDaoTest {
    SqlSession session = null;//sql会话
    Reader reader  = null;//文件输入字符流
    //测试类运行之前执行
    //初始化
    @Before
    public void setUp() throws Exception {
        String resourse = "mybatis-config.xml";
        //加载配置文件,创建会话工厂
        reader = Resources.getResourceAsReader(resourse);
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
        //创建会话对象,相当于JDBC获取连接对象
        session = ssf.openSession(false);
    }
    //测试类运行之后执行
    @After
    public void tearDown() throws Exception {
        session.close();
        reader.close();
    }

    @Test
    public void testQueryClass() {
        //创建会话对象后获取接口对象
        ClassDao dao = session.getMapper(ClassDao.class);
        ClassBean model = new ClassBean();
        //model.setClassTeacher("刘老师");
        model.setClassName("UI");
        //经过上面的工作后,直接调用接口方法即可实现响应的查询。
        //需要传参的可以根据需要直接传基本数据类型,也可以传一个对象,mybatis会获取有值的对象属性作为参数传给MySQL
        List<ClassBean> list = dao.queryClass(model);
        for(ClassBean vo : list){
            //System.out.println(vo.getClassTeacher());
        }
    }
    
    @Test
    public void testInsertClass() {
        try{
            ClassDao dao = session.getMapper(ClassDao.class);
            ClassBean model = new ClassBean();
            //model.setClassTeacher("xxx");
            model.setClassName("javaee");
            model.setClassRoom("1hao");
            
            dao.insertclass(model);
            
            System.out.println(model.getClassId());
            session.commit();
        }catch(Exception e){
            e.printStackTrace();
            session.rollback();
        }
    }
    @Test
    public void testqueryClassByVo(){
        ClassDao dao = session.getMapper(ClassDao.class);
        dao.queryClassByVo(8, "javaee");
    }
    
    @Test
    public void test(){
        ClassDao dao = session.getMapper(ClassDao.class);
        List<ClassBean> list = new ArrayList<ClassBean>();
        ClassBean model = new ClassBean();
        model.setClassId(1);
        list.add(model);
        model = new ClassBean();
        model.setClassId(2);
        list.add(model);
        List<ClassBean> s = dao.queryInfoByIds(list);
    }
    
    @Test
    public void tst(){
        ClassDao dao = session.getMapper(ClassDao.class);
        String ids = "1,2,3,4";
        List<ClassBean> s = dao.queryInfoByIdsaa(ids);
    }
    
    @Test
    public void testQueryAll(){
        ClassDao dao = session.getMapper(ClassDao.class);
        
        List<ClassBean> s = dao.selectByClass();
        for(ClassBean vo : s){
            System.out.println(vo.getTeacher().getcTeacher());
        }
    }
    @Test
    public void findUserById() throws Exception {
    //可以根据查询结果直接调用session的方法,第一个参数是mapper文件的namespace加“.”加方法id,如果需要给数据库传参数则加在第二个参数里。
        List<ClassBean> cb = session.selectList("com.mybatis.myb.dao.ClassDao.selectByClass");
        for (ClassBean classBean : cb) {
            System.out.println(classBean.getTeacher().getcTeacher());
        }
    }
}

补充:mybatis的xml文件实际上就是用来封装MySQL语句和传参的,为了某些需求,一般会把查询条件和一些循环等等用标签做处理。
虽然mybatis没有else标签,但是有另外一种方式可以用于逻辑选择,那就是choose标签。

xml配置:
<select id="findForFalg“ resultMap=“rmClassInfo"> 
SELECT  *  FROM  class_info  WHERE  status = 1
<choose>
    <when test=“flag == 1"> 
        AND room <> #{room} 
    </when> 
    <when test=“flag == 2 "> 
         AND room = #{room} 
    </when> 
    <otherwise>
        AND room like '%${ room }%' 
    </otherwise> 
</choose> 
</select>
说明:
    flag==1:不等于room;flag==2:等于room;否则模糊查询room

一对多补充

编写MapperXML文件

<?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.mybatis.myb.dao.CatgoryDao">
    <resultMap type="Category" id="map1">
        <id column="cat_id" property="catId"/>
        <result column="cat_name" property="catName"/>
        <result column="cat_bak" property="catBak"/>
        <result column="parentid" property="parentId"/>
        <!-- 
            collection:对关联查询到多条记录映射到集合对象中,
            注意:collection用于一对多,association用于一对一
            property:将关联查询到多条记录映射到Category哪个属性
            ofType:指定映射到list集合属性中pojo的类型
         -->
        <collection property="childlist" ofType="Category">
            <id column="scat_id" property="catId"/>
            <result column="scat_name" property="catName"/>
            <result column="scat_bak" property="catBak"/>
            <result column="sparentid" property="parentId"/>
        </collection>
    </resultMap>
    
    <!-- 延迟加载的resultMap -->
    <resultMap type="Category" id="map2">
        <id column="cat_id" property="catId"/>
        <result column="cat_name" property="catName"/>
        <result column="cat_bak" property="catBak"/>
        <result column="parentid" property="parentId"/>
        <!-- 实现对用户信息进行延迟加载
            select:指定延迟加载需要执行的statement的id(是根据column查询用户信息的statement)
            要使用本xml文件中selectByOne和selectByParentid完成根据column查询,如果selectByOne不在本mapper中需要前边加namespace
            column:订单信息中关联用户信息查询的列,是cat_id和parentid
         -->
        <association property="parentCat" column="parentid" select="selectByOne"/><!-- select标签会根据每条数据的parentid再执行一次selectByOne查询 -->
        <collection property="childlist" column="cat_id" select="selectByParentid"/><!-- select标签会根据每条数据的cat_id再执行一次selectByParentid查询  -->
    </resultMap>
    

    <select id="selectByID" resultMap="map2">
        SELECT * FROM t_category where parentid=1
    </select>
    <!-- 二次查询的时候还是原来的表原来的resultMap映射就能实现递归 -->
    <select id="selectByParentid" resultMap="map2">
        SELECT * FROM t_category WHERE parentid=#{xxx} 
    </select>
    <!-- 二次查询的时候还是原来的表原来的resultMap映射就能实现递归 -->
    <select id="selectByOne" resultMap="map2">
        SELECT * FROM t_category where cat_id=#{xxx}
    </select>
    
    <!-- 一对多 -->
    <select id = "selectAll" resultMap = "map1">
        SELECT parent.*
        ,slef.cat_id scat_id
        ,slef.cat_name scat_name
        ,slef.cat_bak scat_bak
        ,slef.parentid sparentid
         FROM t_category parent
        LEFT JOIN t_category slef ON parent.cat_id=slef.parentid
    </select>
        
    <resultMap type="Category" id="map3">
        <id column="cat_id" property="catId"/>
        <result column="cat_name" property="catName"/>
        <result column="cat_bak" property="catBak"/>
        <result column="parentid" property="parentId"/>
    </resultMap>
    
    <select id = "selectAll1" resultMap = "map3">
        SELECT * from t_category
    </select>
    
    <select id="getCount" resultType="int">
        select count(1) as num from t_category 
    </select>
    <!-- 只要能把start和pageSize的值传过来就能实现分页查询 -->
    <select id = "selectByLimit" resultMap="map3">
        select * from t_category 
        limit #{start},#{pageSize}
    </select>
    <!-- 
        补充:resultMap也是可以存在继承关系的,使用extends继承,则子resultMap和父resultMap有相同的映射关系时,子resultMap相同部分可以不写,直接用父resultMap的映射关系
     -->
</mapper>

在mybatis配置文件中注册MapperXML文件

<!-- mapper.xml配置 -->
    <mappers>
        <!--通过resource方法一次加载一个映射文件 -->
        <!-- 通过mapper接口加载单个 映射文件
        遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
        上边规范的前提是:使用的是mapper代理方法
         -->
        <mapper resource="com/mybatis/myb/mapper/classmapper.xml"/>
        <mapper resource="com/mybatis/myb/mapper/catgorymapper.xml"/>
        
        <!-- 批量加载mapper
        指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载
        遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
        上边规范的前提是:使用的是mapper代理方法
         -->
        <!-- <package name="cn.itcast.mybatis.mapper"/> -->
    </mappers>

测试类

package com.mybatis.myb.dao;

import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatis.myb.model.Category;


public class CatgoryDaoTest {

    SqlSession session = null;//sql会话
    Reader reader  = null;//文件输入字符流
    //测试类运行之前执行
    //初始化
    @Before
    public void setUp() throws Exception {
        String resourse = "mybatis-config.xml";
        //加载配置文件,创建会话工厂
        reader = Resources.getResourceAsReader(resourse);
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);
        //创建会话对象,相当于JDBC获取连接对象
        session = ssf.openSession(false);
    }
    //测试类运行之后执行
    @After
    public void tearDown() throws Exception {
        session.close();
        reader.close();
    }


    @Test
    public void test() {
        //获取接口对象
        CatgoryDao dao = session.getMapper(CatgoryDao.class);
        List<Category> list = dao.selectAll();
        System.out.println(list.size());
    }
    
    @Test
    public void test1() {
        //获取接口对象
        CatgoryDao dao = session.getMapper(CatgoryDao.class);
        List<Category> list = dao.select();
        System.out.println(list.size());
    }
    //selectByID
    @Test
    public void testselectByID() {
        //获取接口对象
        CatgoryDao dao = session.getMapper(CatgoryDao.class);
        List<Category> list = dao.selectByID();
        System.out.println(list.size());
    }
    
    
    @Test
    public void testPageInfo() {
        //获取接口对象
        CatgoryDao dao = session.getMapper(CatgoryDao.class);
        //传参
        Category cat = new Category();
        cat.setCurrentPage(4);
        cat.setPageSize(5);
        int count = dao.getCount(cat);
        List<Category> list = new ArrayList<Category>();
        if(count>0){
            list = dao.selectByLimit(cat);
        }
        for(Category c:list) {
            System.out.println("name:"+c.getCatName());
        }
        //com.mybatis.myb.model.PageInfo<Category> pageinfo = new PageInfo<Category>();
        //pageinfo.setTotal(count);
        //pageinfo.setList(list);
        
        
    }
    @Test
    public void testPageInfoPlugin() {
        //获取接口对象
        CatgoryDao dao = session.getMapper(CatgoryDao.class);
        PageHelper.startPage(1, 4);
        List<Category> list = dao.selectAll1();
        PageInfo<Category> info = new PageInfo<Category>(list);
        System.out.println(info.getList().size());
    }
    
}

resultMap总结

resultType:

作用:
  将查询结果按照sql列名pojo属性名一致性映射到pojo中。
场合:
  常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。

resultMap:

  使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。

association:

作用:
  将关联查询信息映射到一个pojo对象中。
场合:
  为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。
  使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。

collection:

作用:
  将关联查询信息映射到一个list集合中。
场合:
  为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。
  如果使用resultType无法将查询结果映射到list集合中。

延迟加载

resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。
需求:
如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。

延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高 数据库性能,因为查询单表要比关联查询多张表速度要快。
要开启延迟加载需要在配置文件中加入如下配置:

    <settings>
        <!-- 打开延迟加载的开关 -->
        <setting name="lazyLoadingEnabled" value="false"/>
        <!-- 将积极加载改为消极加载即按需要加载-->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

说明:时间有限,没有把知识点整理得有条理些,但是已经尽量包含了mybatis的大部分用法了,请将就着看。

网友评论

登录后评论
0/500
评论
我巴巴
+ 关注