MyBatis详解

焦旭峰 于 April 3, 2021

MyBatis详解

第一章 框架概述

1、三层架构

界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet) ​ 业务逻辑层: 接收界面层传递的数据,计算逻辑,调用数据库,获取数据。 ​ 数据访问层: 访问数据库, 执行对数据的增删改查。

1.1、 三层对应的包

​ 界面层: controller包 (servlet) ​ 业务逻辑层: service 包(XXXService类) ​ 数据访问层: dao包(XXXDao类)

1.2、三层中类的交互

用户使用界面层–> 业务逻辑层—>数据访问层(持久层)–>数据库(MySQL)

1.3、三层对应的处理框架

界面层—servlet—springmvc框架 ​ 业务逻辑层—service类–spring框架 ​ 数据访问层—dao类–mybatis框架

2、框架的概念

​ 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种认为,框架是可被应用开发者定制的应用骨架、模板。

​ 简单的说,框架其实是半成品软件,就是一组组件,供你使用完成你自己的系统。从另一个角度来说框架一个舞台,你在舞台上做表演。在框架基础上加入你要完成的功能。

​ 框架安全的,可复用的,不断升级的软件。

3、mybatis框架简介

​ mybatis是一个框架,早期叫做ibatis, 代码在github。mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架),该框架包括sql mapper 和Data Access Objects。

​ MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句。本身,而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。

​ MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 。

对象并返回

1.1、sql mapper

​ 可以把数据库表中的一行数据映射为一个java对象。一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据。

1.2、Data Access Objects(DAOs)

​ 数据访问 , 对数据库执行增删改查。

4、mybatis提供了哪些功能

  1. 提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了

  2. 提供了执行sql语句的能力, 不用你执行sql

  3. 提供了循环sql, 把sql的结果转为java对象, List集合的能力

```
//即代替了如下功能
while (rs.next()) {
	Student stu = new Student();
	stu.setId(rs.getInt("id"));
	stu.setName(rs.getString("name"));
	stu.setAge(rs.getInt("age"));
		//从数据库取出数据转为 Student 对象,封装到 List 集合
	stuList.add(stu);  
}
```

4.提供了关闭资源的能力,不需要开发人员手动关闭Connection, Statement, ResultSet

5、使用MyBatis框架,开发人员需要做什么?

​ 开发人员编写sql语句–>mybatis处理sql—>开发人员得到List集合或java对象(表中的数据)

总结: mybatis是一个sql映射框架,提供了数据库的操作能力。可以看作是一个增强的JDBC,使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet的创建,销毁,sql语句的执行。

第二章 MyBatis框架快速入门

1、主要类的介绍

1.1、Resources类

​ Resources是mybatis中的一个类,负责读取主配置文件

	  InputStream in = Resources.getResourceAsStream("mybatis.xml");
1.2、SqlSessionFactoryBuilder 类

​ SqlSessionFactoryBuilder是负责创建SqlSessionFactory对象的

     SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
    //创建SqlSessionFactory对象
    SqlSessionFactory factory = builder.build(in);
1.3、SqlSessionFactory类 (重点)

​ SqlSessionFactory是重量级对象, 程序创建一个SqlSessionFactory对象耗时比较长,使用资源比较多。在整个项目中,有一个就够用了。

​ SqlSessionFactory接口的实现类是DefaultSqlSessionFactory SqlSessionFactory的作用是通过调用其openSession方法获取SqlSession对象。

SqlSession sqlSession = factory.openSession();
//openSession()方法说明:
//1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
//2. openSession(boolean): openSession(true)  获取自动提交事务的SqlSession. 
 		      			   openSession(false)  非自动提交事务的SqlSession对象
1.4、SqlSession类(重点)

SqlSession接口 定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback() SqlSession接口的实现类是DefaultSqlSession

​ SqlSession使用要求: SqlSession对象不是线程安全的,需要在方法内部使用, 在执行sql语句之前,使用SqlSessionFactory的openSession()获取SqlSession对象。在执行完sql语句后,执行SqlSession.close()关闭SqlSession。 这样能保证他的使用是线程安全的。

第三章 MyBatis框架Dao代理

1、动态代理

使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象,然后再调用对应的增删改查方法,mybatis会通过动态代理帮我们创建这个dao接口的实现对象,无需我们手动创建。

2、传参数: 把数据从java代码中传入到mapper文件的sql语句中。

2.1、parameterType

​ 写在mapper文件中的 一个属性。 表示dao接口中方法的参数的数据类型。

例如:

接口方法:

    Student selectStudentById(@Param("studentId") Integer id);

mapper文件:

    <select id="selectStudentById" parameterType="int" resultType="com.scut.domain.Student">
        select id,name,email,age from student where id = #{studentId}
    </select>
//parameterType也可以不写

测试方法:

    @Test
    public void testSelectStudentById(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        Student student =  dao.selectStudentById(1001);
        System.out.println("student=" + student);
    }
2.2、一个简单类型的参数

​ 简单类型: mybatis把java的基本数据类型和String都叫简单类型。在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}

例如:

接口方法:

    Student selectStudentById(Integer id);

mapper文件:

    <select id="selectStudentById" resultType="com.scut.domain.Student">
        select id,name,email,age from student where id = #{studentId}
    </select>
  //可以不写成studentId,随便写

测试方法:

    @Test
    public void testSelectStudentById(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        Student student =  dao.selectStudentById(1001);
        System.out.println("student=" + student);
    }
2.3、多个参数—使用@Param命名参数(掌握)

​ 语法:在方法形参前面加入@Param(“自定义参数名”),mapper文件使用#{自定义参数名}

接口方法:

List<Student> selectMulitParam(@Param("myname") String name, @Param("myage") Integer age)
//使用  @Param("参数名")  String name  

mapper文件中:

    <!--多个参数,使用@Param命名-->
    <select id="selectMultiParam" resultType="com.scut.domain.Student">
        select id,name,email,age from student where name=#{myname} or age=#{myage}
    </select>

测试方法:

    @Test
    public void testSelectMultiParam() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        List<Student> students = dao.selectMultiParam("李四", 20);
        for (Student stu:students
             ) {
            System.out.println("学生=" + stu);
        }
        sqlSession.close();
    }
2.4、多个参数—使用java对象(掌握)

语法: #{属性名}

接口方法:

  /**
     * 多个参数,使用java对象作为接口中方法的参数
  */   
List<Student> selectMultiObject(QueryParam param);

mapper文件:

    <select id="selectMultiObject" resultType="com.scut.domain.Student">
        select id,name,email,age from student where name=#{paramName} or age=#{paramAge}
    </select><select id="selectMultiObject" resultType="com.scut.domain.Student">
        select id,name,email,age from student where name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
        or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTERGER}
    </select>        
//注意:一般用第一种        

测试方法:

    @Test
    public void testSelectMultiObject() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        QueryParam param  = new QueryParam();
        param.setParamName("张三");
        param.setParamAge(28);
        List<Student> students = dao.selectMultiObject(param);
        for (Student stu:students
        ) {
            System.out.println("学生=" + stu);
        }
        sqlSession.close();
    }
2.5、多个参数—按位置(了解)

​ 语法:#{arg位置}, 第一个参数是#{arg0}, 第二个是#{arg1}

接口方法:

    List<Student> selectMultiPosition(String name,Integer age);

mapper文件:

  <select id="selectMultiPosition" resultType="com.scut.domain.Student">
        select id,name,email,age from student where name=#{arg0} or age=#{arg1}
    </select>

测试方法:

    @Test
    public void testSelectMultiPosition() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        List<Student> students = dao.selectMultiPosition("李四",20);
        for (Student stu:students
        ) {
            System.out.println("学生=" + stu);
        }
        sqlSession.close();
    }
2.6、多个参数—使用Map(了解)

​ Map 集合可以存储多个值,使用Map向mapper文件一次传入多个参数。Map集合使用String类型的key,Object 类型的value存储参数。

​ 语法:#{key}

接口方法:

    List<Student> selectMultiByMap(Map<String,Object> Map);

mapper文件:

   <select id="selectMultiByMap" resultType="com.scut.domain.Student">
        select id,name,email,age from student where name=#{myname} or age=#{age}
    </select>

测试方法:

    @Test
    public void testSelectMultiByMap() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        Map<String,Object> data = new HashMap<>();
        data.put("myname","张三");
        data.put("age",28);

        List<Student> students = dao.selectMultiByMap(data);
        for (Student stu:students
        ) {
            System.out.println("学生=" + stu);
        }
        sqlSession.close();
    }
2.7、#和$(重点)

#:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替 sql 语句的“?”。这样做更安全,更迅速,通常也是首选做法。

mapper文件中:
<select id="selectById" resultType="com.scut.domain.Student">
	select id,name,email,age from student where id=#{studentId}
</select>

转为mybatis执行的是
String sql= select id,name,email,age from student where id=?;
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1005);

解释
where id=? 就是 where id=#{studentId}
ps.setInt(1,1005) , 1005 会替换掉 #{studentId}

$ :字符串替换,告诉 mybatis 使用$包含的“字符串”替换所在位置。使用 Statement 把 sql 语句和${}的 内容连接起来。主要用在替换表名,列名,不同列排序等操作。如果你能确定数据是安全的,可以使用$。

	  select id,name,email,age from student where id=${studentId}
	  $ 的运行结果select id,name, email,age from student where id=1001

	  String sql="select id,name, email,age from student where id=" + "1001";
	  使用的是Statement对象执行sql 效率比PreparedStatement低而且可能导致sql注入

$举例:

接口方法:

    List<Student> selectUse$Order(@Param("colName") String name);

mapper文件:

    <!--$替换列名-->
    <select id="selectUse$Order" resultType="com.scut.domain.Student">
        select * from student order by ${colName}
    </select>

测试方法:

    @Test
    public void testSelectUse$Order() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);


        List<Student> students = dao.selectUse$Order("name");
        for (Student stu:students
        ) {
            System.out.println("学生=" + stu);
        }
        sqlSession.close();
    }
2.7.1、#和 $区别(重点)

​ 1、# 使用 ?在sql语句中做占位的, 使用PreparedStatement执行sql,效率高 ​ 2、#能够避免sql注入,更安全。 ​ 3、 $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低 ​ 4、 $有sql注入的风险,缺乏安全性。 ​ 5、 $:可以替换表名或者列名

3、mybatis的输出结果

mybatis执行了sql语句,得到java对象。

3.1、resultType

​ resultType是结果类型,指的是sql语句执行完毕后, 数据转为的java对象, java类型是任意的。

注意:resultSet和resultType不能同时使用。

3.1.1、resultType结果类型

1、类型的全限定名称(建议使用) 2、类型的别名

例如 java.lang.Integer是全限定名称,别名是int。

3.1.2、resultType的处理方式

​ 1、mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象。

​ 2、mybatis把ResultSet指定列值赋给同名的属性。

mapper文件中:	
	<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
      select id,name, email,age from student
    </select>

上述sql语句与下面的jdbc对等:

	  ResultSet rs = executeQuery(" select id,name, email,age from student" )
	  while(rs.next()){
           Student  student = new Student();
				student.setId(rs.getInt("id"));
				student.setName(rs.getString("name"))
	  }
3.2、定义自定义类型的别名

定义自定义类型别名的步骤:

1、在mybatis主配置文件中定义,使定义别名

​ 有两种定义别名的方式:1、,2、

   <!--定义别名-->
    <typeAliases>
        <!--
            第一种方式:
            可以指定一个类型一个自定义别名
            type:自定义类型的全限定名称
            alias:别名(短小,容易记忆的)
        -->
       <!-- <typeAlias type="com.scut.domain.Student" alias="stu"/>
        <typeAlias type="com.scut.vo.ViewStudent" alias="vstu"/>-->

        <!--
        第二种方式(常用 )
        <package> name是包名,这个包中的所有类,类名是别名(类名不区分大小写)
        -->
        <package name="com.scut.domain"/>
        <package name="com.scut.vo"/>
    </typeAliases>

2、然后在mapper文件中,resultType使用自定义别名

3.3、resultMap

resultMap是结果映射, 指定列名和java对象的属性对应关系。可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。 常用在列名和 java 对象属性名不一样的情况。

3.3.1、resultMap的使用方式

1、先定义resultMap

2、在select标签,使用resultMap来引用1中定义的resultMap

    <!--定义resultMap
        id:自定义名称,表示你定义的这个resultMap
        type:java类型的全限定名称
    -->   
	<resultMap id="studentMap" type="com.scut.domain.Student">
        <!--列名和java属性的关系-->
        <!--注解列,使用id标签
            column:列名
            property:java类型的属性名
        -->
        <id column="id" property="id"/>
        <!--主键列,使用result-->
        <result column="name" property="name"/>
        <result column="email" property="email"/>
        <result column="age" property="age"/>
    </resultMap>
    <select id="selectAllStudents" resultMap="studentMap">
        select id,name,email,age from student
    </select>
3.3.1、resultMap的作用

​ 1)指定自定义列值赋值给哪个属性 ​ 2)当你的列名和属性名不一样时,一定使用resultMap

注意:resultMap和resultType不要一起用,二选一

3.3.2、列名和属性值不一样时的两种解决方案

​ 第一种解决方案:resultMap(常用)

例如:

   <resultMap id="mystudentMap" type="com.scut.domain.MyStudent">
        <!--列名和java属性的关系-->
        <!--非主键列,使用id-->         
        <id column="id" property="stuid"/>
        <!--主键列,使用result-->
        <result column="name" property="stuname"/>
        <result column="email" property="stuemail"/>
        <result column="age" property="stuage"/>
    </resultMap>
    <!--列名和属性名不一样:第一种方式-->
    <select id="selectMyStudent" resultMap="mystudentMap">
        select id,name,email,age from student
    </select>

​ 第二种解决方案:使用sql语句的列别名

    <!--列名和属性名不一样:第二种方式
        resultType的默认原则是:同名的列值赋值给同名的属性,使用列别名(java对象的属性名)
    -->
    <select id="selectDiffColProperty" resultType="com.scut.domain.MyStudent">
        select id as stuid,name as stuname,email as stuemail,age as stuage from student
    </select>
3.4、模糊like

​ 模糊查询的实现方式有两种:java代码中给查询数据加上”%“,在mapper文件sql语句的条件位置加上”%”

3.4.1、java代码中给查询数据加上”%“(常用)

例如:

接口方法:

    /*第一种模糊查询,在java代码指定like的内容*/
    List<Student> selectLikeOne(String name);

mapper文件:

   <!--第一种like,java代码指定like的内容-->
    <select id="selectLikeOne" resultType="com.scut.domain.Student">
        select id,name,email,age from student where name like #{name}
    </select>

测试方法:

    @Test
    public void testSelectLikeOne() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //准备好like的内容
        String name = "%李%";
        List<Student> students = dao.selectLikeOne(name);
        for (Student   stu:students
        ) {
            System.out.println("#######学生=" + stu);
        }
        sqlSession.close();
    }
3.4.2、在mapper文件sql语句的条件位置加上”%“

接口方法:

    /*第二种模糊查询,name就是李值,在mapper中拼接like "%" 李 "%" */
    List<Student> selectLikeTwo(String name);

mapper文件:

     <!--第二种方式,在mapper文件中拼接like的内容-->
    <select id="selectLikeTwo" resultType="com.scut.domain.Student">
        select id,name,email,age from student where name like "%" #{name} "%"
    </select>

测试方法:

    @Test
    public void testSelectLikeTwo() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //准备好like的内容
        String name = "李";
        List<Student> students = dao.selectLikeTwo(name);
        for (Student   stu:students
        ) {
            System.out.println("********学生=" + stu);
        }
        sqlSession.close();
    }

第四章 MyBatis框架动态SQL

​ 动态SQL指的是SQL的内容是变化的,可以根据条件获取到不同的sql语句。主要是where部分发生变化。动态SQL主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行查询。

​ 在mapper的动态SQL中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等 符号,最好将其转换为实体符号。否则,XML 可能会出现解析出错问题。

动态SQL的实现,使用的是mybatis提供的标签, ,,

1、if标签

1.1、语法
   	<if test="判断java对象的属性值">
            部分sql语句
	</if>

​ 对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。

1.2、举例

接口方法:

    //动态sql,使用java对象作为参数
    List<Student> selectStudentIf(Student student);

mapper文件:

    <!--if
        <if:test="使用参数java对象的属性值作为判断条件,语法 属性=xxx值">
    -->
    <select id="selectStudentIf" resultType="com.scut.domain.Student">
        select id,name,age,email from student
        where 1=1
        <if test="name !=null and name != ''">
             name = #{name}
        </if>
        <if test="age > 0">
            or age &gt; #{age}
        </if>
    </select>
//1=1是为了防止SQL语句出错

测试方法:

    @Test
    public void testSelectStudentById(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        Student student = new Student();
//        student.setName("李四");
//        student.setAge(18);

//        student.setName("李四");
        student.setAge(18);
        List<Student> students = dao.selectStudentIf(student);
        for (Student stu:
             students) {
            System.out.println("if==" + stu);
        }
    }

2、where标签

​ if标签存在的问题是必须在where后面加上1=1。where可以解决这个问题。

​ where标签是用来包含多个if标签的,当多个if中有一个成立时,where标签会自动增加一个where关键字,并去掉if中多余的and ,or等。

2.1、语法
<where>
    其他动态sql
</where>
2.2、举例

接口方法:

   //where标签
    List<Student> selectStudentWhere(Student student);

mapper文件:

    <!--
        where:<where> <if> <if>...<where>
    -->
    <select id="selectStudentWhere" resultType="com.scut.domain.Student">
        select id,name,email,age from student
        <where>
            <if test="name !=null and name != ''">
                name = #{name}
            </if>
            <if test="age > 0">
                or age > #{age}
            </if>
        </where>
    </select>

测试方法:

   @Test
    public void testSelectStudentWhere(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        Student student = new Student();
        student.setName("李四");
        student.setAge(18);


        List<Student> students = dao.selectStudentWhere(student);
        for (Student stu:
                students) {
            System.out.println("where==" + stu);
        }
    }

3、foreach标签

​ foreach标签是用来循环java中的数组,list集合的。主要用在sql的in语句中。

例如:学生id是 1001,1002,1003的三个学生
 	select * from student where id in (1001,1002,1003)

 接口方法:
 public List<Student> selectFor(List<Integer> idlist)
 测试方法:
 List<Integer> list = new ...
 list.add(1001);
 list.add(1002);
 list.add(1003);
 dao.selectFor(list)
3.1、语法
 <foreach collection="集合类型" item="集合中的成员" open="开始的字符" close="结束的字符" separator="集合成员之间的分隔符">
         #{item的值}
</foreach>

collection:表示接口中的方法参数的类型, 如果是数组使用array , 如果是list集合使用list
 item:自定义的,表示数组和集合成员的变量
 open:循环开始时的字符
 close:循环结束时的字符
separator:集合成员之间的分隔符
3.2、举例

例1,**遍历List<简单类型>**

接口方法:

    List<Student> selectForeachOne(List<Integer> idlist);

mapper文件:

    <!--foreach使用1 , List<Integer>-->
    <select id="selectForeachOne" resultType="com.scut.domain.Student">
        select * from student where id in
        <foreach collection="list" item="myid" open="(" close=")" separator=",">
            #{myid}
        </foreach>
    </select>

测试方法:

    @Test
    public void testSelectForeachOne(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        List<Integer> list = new ArrayList<>();
        list.add(1005);
        list.add(1006);
        list.add(1007);


        List<Student> students = dao.selectForeachOne(list);
        for (Student stu:
                students) {
            System.out.println("foreach--one ===" + stu);
        }
    }

例2,**遍历List<引用类型>**

接口方法:

    List<Student> selectForeachTwo(List<Student> stuList);

mapper文件:

    <select id="selectForeachTwo" resultType="com.scut.domain.Student">
        select id,name,email,age from student where id in (
        <foreach collection="list" item="stu" >
            #{stu.id},
        </foreach>
        -1 )
    </select>

测试方法:

    @Test
    public void testSelectForeachTwo(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        List<Student> stuList = new ArrayList<>();
        Student stu1 = new Student();
        stu1.setId(1001);
        stuList.add(stu1);

        stu1 = new Student();
        stu1.setId(1005);
        stuList.add(stu1);

        List<Student> students = dao.selectForeachTwo(stuList);
        for (Student stu:
                students) {
            System.out.println("foreach--two ===" + stu);
        }
    }

4、SQL代码片段

​ SQL代码片段是供其他SQL标签复用的。

​ </sql>标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用 </include>子标签。该标签可以定义 SQL 语句中的任何部分,所以</include>子标签可以放在动态 SQL 的任何位置。

4.1、使用步骤
	1.先定义 <sql id="自定义名称唯一">  sql语句, 表名,字段等 </sql>
    2.再使用, <include refid="id的值" />
4.2、举例

例1:

mapper文件中定义sql片段:

    <sql id="studentSql">
        select id,name,age,email from student
    </sql>

mapper文件sql语句中使用该片段:

    <select id="selectForeachTwo" resultType="com.scut.domain.Student">
        <include refid="studentSql"></include> where id in (
        <foreach collection="list" item="stu" >
            #{stu.id},
        </foreach>
        -1 )
    </select>

例2:

mapper文件中定义sql片段:

    <sql id="studentSqlOne">
        id,name,age,email
    </sql>

mapper文件sql语句中使用该片段:

    <select id="selectStudentIf" resultType="com.scut.domain.Student">
        select <include refid="studentSqlOne"></include> from student
        where 1=1
        <if test="name !=null and name != ''">
             and name = #{name}
        </if>
        <if test="age > 0">
            or age > #{age}
        </if>
    </select>

第五章 MyBatis配置文件

1、数据库的属性配置文件

​ 把数据库连接信息放到一个单独的属性配置文件中。使其和mybatis主配置文件分开。目的是便于修改,保存,处理多个数据库的信息。

1)首先在resources目录中定义一个属性配置文件, xxxx.properties ,例如 jdbc.properties 在属性配置文件中, 定义数据,格式是 key=value 。其中key 一般使用 . 做多级目录的。例如 jdbc.mysql.driver, jdbc.driver, mydriver

例如,jdbc.propertied如下:

	  jdbc.driver=com.mysql.jdbc.Driver
	  jdbc.url=jdbc:mysql://localhost:3306/springdb?useUnicode=true&amp;characterEncoding=utf-8
	  jdbc.username=root
	  jdbc.passwd=123456

2)**然后在mybatis的主配置文件,使用 指定文件的位置。在需要使用值的地方, ${key}。**

            <dataSource type="POOLED">
                <!--数据库的驱动类名-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--连接数据库的url字符串-->
                <property name="url"
                          value="${jdbc.url}"/>
                <!--访问数据库的用户名-->
                <property name="username" value="${jdbc.user}"/>
                <!--密码-->
                <property name="password" value="${jdbc.passwd}"/
            </dataSource>

2、mapper文件,使用package指定路径

<mapper>   
   <!--第二种方式: 使用包名
        name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis
        使用package的要求:
         1. mapper文件名称需要和接口名称一样, 区分大小写的一样
         2. mapper文件和dao接口需要在同一目录
    -->
    <package name="com.bjpowernode.dao"/>
</mappers>

还有第一种方式如下,指定多个mapper文件该方式不推荐使用该方式。

<mapper resource="com/scut/dao/StudentDao.xml"/>

第六章 PageHelper

​ PageHelper做数据分页的。实现多种数据库的分页,mysql就是代替limit语句的。

1、PageHelper的使用步骤

1)首先在pom.xml中加入PageHelper依赖

    <!--PageHelper依赖-->
    <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.10</version>
    </dependency>

2)mybatis主配置文件中加入plugin配置

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

3)查询语句之前,调用PageHelper.startPage静态方法

    @Test
    public void testSelectAllPageHelper(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //加入PageHelper的方法,分页
        //pageNum:第几页,从1开始
        //pageSize:一页有多少行数据
        PageHelper.startPage(3,3);
        List<Student> students = dao.selectAll();
        for (Student stu:
                students) {
            System.out.println("foreach--two ===" + stu);
        }
    }

第七章 mybatis的使用步骤

​ 本章举例说明mybatis的使用方法

7.1、项目中加入maven的依赖

​ 首先项目的pom.xml文件中加入mybatis和mysql依赖

    <!--mybatis依赖-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>

    <!--mysql数据库依赖-->
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>

7.2、创建实体类

​ 该类对应于数据库中的一张表

package com.scut.domain;

public class Student {

    private Integer id;
    private String name;
    private String email;
    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }
}

7.3、创建Dao接口

​ 然后创建一个com.scut.dao接口,在该接口定义操作数据的方法

package com.scut.dao;

import com.scut.domain.Student;
import com.scut.vo.QueryParam;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

//dao接口中不要使用重载方法,不要使用同名的,不同参数的方法
public interface StudentDao {
    Student selectStudentById(@Param("studentId") Integer id);
}

74、创建mapper文件

​ 在com.scut.dao包中创建mapper文件:

<?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.scut.dao.StudentDao">
    <select id="selectStudentById" parameterType="int" resultType="com.scut.domain.Student">
        select id,name,email,age from student where id=#{studentId}
    </select>
</mapper>

7.5、创建mybatis的主配置文件

​ 在src/main/resources目录下创建mybatis.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>

    <!--settings:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <environments default="mydev">
        <environment id="mydev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库的驱动类名-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url"
                          value="jdbc:mysql://localhost:3306/db?useUnicode=true&amp;characterEncoding=utf-8"/>
                <!--访问数据库的用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>

    </environments>

    <!-- sql mapper(sql映射文件)的位置-->
    <mappers>
        <mapper resource="com/scut/dao/StudentDao.xml"/>
        <!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml" />-->
    </mappers>
</configuration>

7.6、执行sql

package com.scut;

import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.dao.impl.StudentDaoImpl;
import com.bjpowernode.domain.Student;
import org.junit.Test;

public class TestMyBatis {
    @Test
    public void testSelectStudentById(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        Student student =  dao.selectStudentById(1001);
        System.out.println("student=" + student);
    }
}

补充

​ vo包: value object , 放一些存储数据的类。比如说 提交请求参数,name ,age ,例如把name ,age 传给一个service 类。

​ vo包: view object , 从servlet把数据返回给浏览器使用的类,表示显示结果的类。

​ pojo包: 普通的有set, get方法的java类。

​ Servlet — StudentService( addStudent( MyParam param) )

​ entity包(domain域): 实体类, 和数据库中的表对应的类,。