Mybatis最详细入门

1. 框架概述

1.1 什么是框架

能够说,一个框架是一个可复用的设计构件,它规定了应用的体系结构,阐明了整个设计、协做构件之间的依赖关系、责任分配和控制流程,表现为一组抽象类以及其实例之间协做的方法,它为构件复用提供了上下文(Context)关系。所以构件库的大规模重用也须要框架。html

1.2 为何使用框架

  • 由于软件系统发展到今天已经很复杂了,特别是服务器端软件,涉及到的知识,内容,问题太多。java

  • 在某些方面使用别人成熟的框架就至关于让别人帮你完成一些基础工做,你只须要集中精力完成系统的业务逻辑设计mysql

  • 并且框架通常是成熟,稳健的,它能够处理系统不少细节问题,好比,事务处理,安全性,数据流控制等问题。git

  • 还有框架通常都通过不少人使用,因此结构很好,因此扩展性也很好,并且它不断升级的,你能够直接享受别人升级代码带来的好处程序员

1.3 软件开发的三层架构

  • 咱们用三层结构主要是使项目结构更清楚,分工更明确,有利于后期的维护和升级.github

  • 三层架构包含:表现层业务层持久化层sql

     

2. MyBatis介绍

2.1 MyBatis概述

  • MyBatis参考网址:http://www.mybatis.org/mybatis-3/zh/index.html数据库

  • MyBatis什么?apache

    • MyBatis是一个优秀的持久层框架,它是一个半自动化的ORM框架编程

    • 使用JDBC操做数据库的过程进行封装,使开发者只须要关注 SQL 自己,而不须要花费精力去处理例如注册驱动、建立connection、建立statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

  • MyBatis由来?

    • MyBatis 本是apache的一个开源项目iBatis

    • 2010年这个项目由apache software foundation 迁移到了google code,而且更名为MyBatis 。

    • 2013年11月迁移到Github。

  • Mybatis在哪写SQL语句?如何设置SQL参数和封装查询结果?

    • Mybatis经过XML注解的方式,将要执行的各类statement(statement、preparedStatemnt、CallableStatement)配置起来。

    • 并经过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

2.2 JDBC示例代码

public class JDBCTest {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;

try {
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");

// 经过驱动管理类获取数据库连接connection = DriverManager
connection = DriverManager.getConnection(
                          "jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8",
                       "root",
                            "root"
            );

// 定义sql语句 ?表示占位符
String sql = "select * from user where username = ?";
// 获取预处理 statement
preparedStatement = connection.prepareStatement(sql);

// 设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的
preparedStatement.setString(1, "王五");
// 向数据库发出 sql 执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
// 遍历查询结果集
while (resultSet.next()) {
System.out.println(
                       resultSet.getString("id")
                       + " " +
                        resultSet.getString("username")
              );
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block e.printStackTrace();
}
}
}
}
}

 

2.3 Mybatis如何解决JDBC代码中存在的问题(掌握)

  1. 建立数据库链接相关操做,存在硬编码

    • 解决方案:经过Mybatis全局配置文件,对数据库链接进行配置

  2. statement相关操做,存在硬编码

    • 解决方案:经过Mapper映射文件,对statement相关处理进行配置。

  3. 频繁开启数据库链接,会下降数据库处理性能。

    • 解决方案:经过Mybatis全局配置文件,配置链接池

2.4 Mybatis工做原理(重点)

  • 咱们要找出的答案就是:从XML配置文件到数据库的距离有多长?

     

  • 说明

    1. mybatis配置文件

      • SqlMapConfig.xml,此文件做为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

      • Mapper.xml,此文件做为mybatis的sql映射文件,文件中配置了操做数据库的sql语句。此文件须要在SqlMapConfig.xml中加载。

    2. SqlSessionFactory

      • 经过mybatis环境等配置信息构造SqlSessionFactory,即会话工厂。

    3. SqlSession

      • 经过会话工厂建立sqlSession即会话,程序员经过sqlsession会话接口对数据库进行增删改查操做。

    4. Executor执行器

      • mybatis底层自定义了Executor执行器接口来具体操做数据库,Executor接口有两个实现,一个是基本执行器(默认)、一个是缓存执行器,sqlsession底层是经过executor接口操做数据库的。

    5. Mapped Statment

      • 它也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个select\insert\update\delete标签对应一个Mapped Statement对象,select\insert\update\delete标签的id便是Mapped statement的id。

      • Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor经过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对prepared Statement设置参数。

      • Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor经过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程至关于jdbc编程中对结果的解析处理过程。

2.5 MyBatis 核心组件的生命周期

  • SqlsessionFactoryBuilder:方法级别, 方法执行完直接销毁

  • SqlsessionFactory:全局范围(应用级别), 能够看做是一个链接池,只存在一个,使用单例

  • Sqlsession:方法级别,一个操做对应一个Sqlsession

3. MyBatis入门

3.1 需求

  1. 根据用户id查询一个学生信息

  2. 根据用户名称模糊查询用户信息列表

  3. 添加学生

  4. 根据id来更新学员的信息

  5. 根据id来删除学生

3.2 MyBatis开发框架搭建(重点)

  • 建立maven工程,在pom文件中引入mybatis等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.hwua</groupId>
    <artifactId>HelloMyBatis2019.6.11</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
    </dependency>

    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.15</version>
    </dependency>

    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    </dependency>

    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.8.0-beta2</version>
    <scope>test</scope>
    </dependency>
    </dependencies>
    </project>
  • 建立数据库属性文件db.properties

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:8888/mybatisdb
    username=root
    password=123456
  • 建立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"/><!--加载属性文件 -->
    <!--配置运行环境  -->
     <environments default="development">
       <environment id="development">
         <!--使用mybatis自带的jdbc事务管理机制  -->
         <transactionManager type="JDBC"/>
         <!--使用mybatis自带的链接池技术 -->
         <dataSource type="POOLED">
           <property name="driver" value="${driver}"/><!--读取属性文件中的key:driver-->
           <property name="url" value="${url}"/>
           <property name="username" value="${username}"/>
           <property name="password" value="${password}"/>
         </dataSource>
       </environment>
     </environments>
     <mappers>
       <mapper resource="StudentMapper.xml"/><!-- 引入映射器文件 -->
     </mappers>
    </configuration>
  • 建立log4j日志记录配置文件

    log4j.rootLogger=debug, stdout
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

     

  • 配置映射器文件( StudentMapper.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">
    <mapper namespace="test">
    <!--配置sql查询语句 ,parameterType 设置输入参数的数据类型, resultType 设置输出参数的数据类型-->
     <select id="queryStudentById" parameterType="int" resultType="com.hwua.pojo.Student">
       select * from Student where id = #{id}
     </select>
    </mapper>
  • 建立pojo类

    package com.hwua.pojo;

    public class Student {
    private Integer id;
    private String sno;
    private String sname;
    private String ssex;
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public String getSno() {
    return sno;
    }
    public void setSno(String sno) {
    this.sno = sno;
    }
    public String getSname() {
    return sname;
    }
    public void setSname(String sname) {
    this.sname = sname;
    }
    public String getSsex() {
    return ssex;
    }
    public void setSsex(String ssex) {
    this.ssex = ssex;
    }
    @Override
    public String toString() {
    return "Student [id=" + id + ", sno=" + sno + ", sname=" + sname + ", ssex=" + ssex + "]";
    }

    }

 

4.使用SqlSession发送SQL来实现业务需求

4.1 根据用户id查询一个学生信息

  • 映射文件

    <?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="test">
    <!--配置sql查询语句 ,parameterType 设置输入参数的数据类型, resultType 设置输出参数的数据类型-->
     <select id="queryStudentById" parameterType="int" resultType="com.hwua.pojo.Student">
       select * from Student where id = #{id}
     </select>
    </mapper>
  • 测试代码

     
  • 源码解析:

    • SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));解析主配置文件,把配置文件中的信息保存到Configuration对象,并获得一个DefaultSqlSessionFactory对象

    • XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());解析mapper文件

    • SqlSession sqlSession = sessionFactory.openSession();获取运行环境,建立一个Executor对象,并返回DefaultSqlSession对象

    • 当执行selectOne方法的时候其实底层交给SimpleExecutor对象调用query方法来进行处理,

    • 在调用query方法的时候底层会产生一个MapperStatement对象,此对象用来进行封装sql语句,讲封装好的sql语句交给执行器来进行执行.

    • 执行返回的结果交给ResultHandler来进行封装成返回结果.

4.2 根据学生名称模糊查询学生信息列表

  • 映射文件

     <select  id="queryStudentByNameLike" parameterType="string" resultType="com.hwua.pojo.Student">
        <!-- select * from Student where sname like concat('%',#{name},'%') -->
        <!-- select * from Student where sname like #{name} -->
        select * from Student where sname like '%${value}%'
      </select>
    
  • 测试代码

    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
    		SqlSession sqlSession = sessionFactory.openSession();
    		/*Student stu =(Student)sqlSession.selectOne("test.queryStudentById", 1);
    		System.out.println(stu);*/
    		List<Student> stuList = sqlSession.selectList("queryStudentByNameLike", "张");
    		System.out.println(stuList);
    
  • #{}和${}区别(重点)

    区别1:

    1. #{} :至关于JDBC SQL语句中的占位符? (PreparedStatement)

    2. ${} 至关于JDBC SQL语句中的链接符合 +(Statement)

    区别2:

    1. #{} : 进行输入映射的时候,会对参数进行类型解析(若是是String类型,那么SQL语句会自动加上’’)

    2. ${} :进行输入映射的时候,将参数原样输出到SQL语句中

    区别3:

    1. #{} : 若是进行简单类型(String、Date、8种基本类型的包装类)的输入映射时,#{}中参数名称能够任意

    2. ${} 若是进行简单类型(String、Date、8种基本类型的包装类)的输入映射时,${}中参数名称必须是value

    注意:${} :存在SQL注入问题,使用OR 1=1 关键字将查询条件忽略

  • OGNL

    OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,他是一个开源项目。Struts框架使用OGNL做为默认的表达式语言。

    Student

    -- name

    -- age

    --teacher

    -- name

    -- age #{student.teacher.age}

4.3 添加用户

  • 映射文件

    <insert id="saveStudent" parameterType="com.hwua.pojo.Student">
         insert into student values(null,#{sno},#{sname},#{ssex})
      </insert>
    
  • 测试代码

    SqlSession sqlSession = null;
    		try {
    			SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
    					.build(Resources.getResourceAsStream("mybatis-config.xml"));
    			sqlSession = sessionFactory.openSession();
    			Student stu = new Student();
    			stu.setSname("jack");
    			stu.setSno("no006");
    			stu.setSsex("男");
    			int res = sqlSession.insert("test.saveStudent", stu);
    			sqlSession.commit();// 提交事务
    			System.out.println(res);
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    

4.4 更新用户

  • 映射文件

    <update id="updateStudent" parameterType="com.hwua.pojo.Student">
         update student set sno=#{sno},sname=#{sname},ssex=#{ssex} where id = #{id}
      </update>
    
  • 测试代码

    SqlSession sqlSession = null;
    		try {
    			SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
    					.build(Resources.getResourceAsStream("mybatis-config.xml"));
    			sqlSession = sessionFactory.openSession();
    			Student stu = (Student) sqlSession.selectOne("test.queryStudentById", 1);
    			stu.setSname("mary");
    			stu.setSsex("女");
    			int res = sqlSession.update("test.updateStudent", stu);
    			sqlSession.commit();// 提交事务
    			System.out.println(res);
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    

4.5 删除用户

  • 映射文件

    <delete id="deleteStudent" parameterType="int">
      	delete from student where id = #{id}
      </delete>
    
  • 测试代码

    SqlSession sqlSession = null;
    		try {
    		SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
    					.build(Resources.getResourceAsStream("mybatis-config.xml"));
    			sqlSession = sessionFactory.openSession();
    			int res = sqlSession.delete("test.deleteStudent", 6);
    			sqlSession.commit();// 提交事务
    			System.out.println(res);
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    

     

5.使用原始Dao的开发方式来开发Dao层

5.1 dao的接口和实现类和工具类

//接口
public interface StudentDao {
   Student findStudentById(Integer id) throws Exception;
   List<Student> findStudentByName(String name) throws Exception;
   int saveStudent(Student student) throws Exception;
   int updateStudent(Student student) throws Exception;
   int deleteStudent(Integer id) throws Exception;
}

//实现类
public class StudentDaoImpl implements StudentDao {

	@Override
	public Student findStudentById(Integer id) throws Exception {
		Student stu = null;
		SqlSession sqlSession = null;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			stu = (Student) sqlSession.selectOne("queryStudentById", id);
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return stu;
	}

	@Override
	public List<Student> findStudentByName(String name) throws Exception {
		List<Student> stuList = null;
		SqlSession sqlSession = null;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			stuList = sqlSession.selectList("queryStudentByNameLike", name);
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return stuList;
	}

	@Override
	public int saveStudent(Student student) throws Exception {
		SqlSession sqlSession = null;
		int res =0;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			res = sqlSession.insert("saveStudent", student);
			sqlSession.commit();
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return res;
	}

	@Override
	public int updateStudent(Student student) throws Exception {
		SqlSession sqlSession = null;
		int res =0;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			res = sqlSession.update("updateStudent", student);
			sqlSession.commit();
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return res;
	}

	@Override
	public int deleteStudent(Integer id) throws Exception {
		SqlSession sqlSession = null;
		int res =0;
		try {
			sqlSession = SqlSessionFactoryUtils.getSqlSession();
			res = sqlSession.delete("deleteStudent", id);
			sqlSession.commit();
		} finally {
			if(sqlSession!=null) {
				sqlSession.close();
			}
		}
		return res;
	}

}

//工具类
public class SqlSessionFactoryUtils {
	private static SqlSessionFactory sessionFactory = null;

	//单例去建立SqlSessionFactory
	private static SqlSessionFactory getInstance() throws Exception {
		if (sessionFactory == null) {
			synchronized (SqlSessionFactoryUtils.class) {
				if (sessionFactory == null) {
					sessionFactory = new SqlSessionFactoryBuilder()
							.build(Resources.getResourceAsStream("mybatis-config.xml"));
				}
			}
		}
		return sessionFactory;
	}

	//获得SqlSession
	public static SqlSession getSqlSession() throws Exception {
		SqlSessionFactory sqlSessionFactory = getInstance();
		return sqlSessionFactory.openSession();
	}
}

5.2 映射文件

<?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="test">
<!--配置sql查询语句 ,parameterType 设置输入参数的数据类型, resultType 设置输出参数的数据类型-->
  <select  id="queryStudentById" parameterType="int" resultType="com.hwua.pojo.Student">
    select * from Student where id = #{id}
  </select>
  <select  id="queryStudentByNameLike" parameterType="com.hwua.pojo.Student" resultType="com.hwua.pojo.Student">
    <!-- select * from Student where sname like concat('%',#{name},'%') --> 
    <!-- select * from Student where sname like #{name} -->
    select * from Student where sname like '%${value}%'
  </select>
  
  <insert id="saveStudent" parameterType="com.hwua.pojo.Student">
     insert into student values(null,#{sno},#{sname},#{ssex})
  </insert>
  <update id="updateStudent" parameterType="com.hwua.pojo.Student">
     update student set sno=#{sno},sname=#{sname},ssex=#{ssex} where id = #{id}
  </update>
  <delete id="deleteStudent" parameterType="int">
  	delete from student where id = #{id}
  </delete>
  
</mapper>

5.3 测试代码

package com.hwua.test;

import org.junit.Before;
import org.junit.Test;

import com.hwua.pojo.Student;
import com.hwua.service.StudentService;
import com.hwua.service.impl.StudentServiceImpl;

public class StudentTest {
	private StudentService stuService=null;
	@Before
	public void init() {
		stuService = new StudentServiceImpl();
	}
	@Test
	public void testFindStudentById() {
		try {
			Student stu = stuService.findStudentById(1);
			System.out.println(stu);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

6.使用Mapper接口发送SQL(重点)

6.1 XML实现映射器

  • 使用:只须要开发Mapper接口(dao接口)和Mapper约束文件,不须要编写实现类。

  • 开发规范: Mapper接口开发须要遵循如下规范:

    • Mapper接口的类路径与Mapper.xml文件中的namespace相同。

    • Mapper接口方法名称和Mapper.xml中定义的每一个statement的id相同。

    • Mapper接口方法的输入参数类型和mapper.xml中定义的每一个sql 的parameterType的类型相同。

    • Mapper接口方法的返回值类型和mapper.xml中定义的每一个sql的resultType的类型相同。

  • mapper接口

    package com.hwua.mapper;
    import java.util.List;
    import com.hwua.pojo.Student;
    public interface StudentMapper {
       Student findStudentById(Integer id) throws Exception;
       List<Student> findStudentByName(String name) throws Exception;
       int saveStudent(Student student) throws Exception;
       int updateStudent(Student student) throws Exception;
       int deleteStudent(Integer id) throws Exception;
    }
    
    
  • 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.hwua.mapper.StudentMapper">
    <!--配置sql查询语句 ,parameterType 设置输入参数的数据类型, resultType 设置输出参数的数据类型-->
      <select  id="findStudentById" parameterType="int" resultType="com.hwua.pojo.Student">
        select * from Student where id = #{id}
      </select>
      <select  id="findStudentByName" parameterType="string" resultType="com.hwua.pojo.Student">
        <!-- select * from Student where sname like concat('%',#{name},'%') --> 
        <!-- select * from Student where sname like #{name} -->
        select * from Student where sname like '%${value}%'
      </select>
      
      <insert id="saveStudent" parameterType="com.hwua.pojo.Student">
         insert into student values(null,#{sno},#{sname},#{ssex})
      </insert>
      <update id="updateStudent" parameterType="com.hwua.pojo.Student">
         update student set sno=#{sno},sname=#{sname},ssex=#{ssex} where id = #{id}
      </update>
      <delete id="deleteStudent" parameterType="int">
      	delete from student where id = #{id}
      </delete>
      
    </mapper>
    
  • 主配置文件加载映射文件

    <?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"/><!--加载属性文件 -->
    <!--配置运行环境  -->
      <environments default="development">
        <environment id="development">
          <!--使用mybatis自带的jdbc事务管理机制  -->
          <transactionManager type="JDBC"/>
          <!--使用mybatis自带的链接池技术 -->
          <dataSource type="POOLED">
            <property name="driver" value="${driver}"/><!--读取属性文件中的key:driver-->
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          </dataSource>
        </environment>
      </environments>
     
      <mappers>
        <mapper resource="com/hwua/mapper/StudentMapper.xml"/><!-- 引入映射器文件 -->
      </mappers>
    </configuration>
    
  • 测试代码

    package com.hwua.mapper;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.hwua.pojo.Student;
    import com.hwua.utils.SqlSessionFactoryUtils;
    
    public class StudentMapperTest {
    	@Test
    	public void testFindStudentById() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			// 建立了StudentMapper接口的一个代理类对象
    			StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    			Student stu = mapper.findStudentById(1);
    			System.out.println(stu);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    	
    	@Test
    	public void testSaveStudent() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			// 建立了StudentMapper接口的一个代理类对象
    			StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    			Student stu = new Student();
    			stu.setSname("frank");
    			stu.setSno("no006");
    			stu.setSsex("男");
    			int res=mapper.saveStudent(stu);
    			sqlSession.commit();
    			System.out.println(res);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    	
    	@Test
    	public void testUpdateStudent() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			// 建立了StudentMapper接口的一个代理类对象
    			StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    			Student stu = mapper.findStudentById(1);
    			stu.setSname("jackson");
    			stu.setSsex("男");
    			int res=mapper.updateStudent(stu);
    			sqlSession.commit();
    			System.out.println(res);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    	
    	@Test
    	public void testDeleteStudent() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			// 建立了StudentMapper接口的一个代理类对象
    			StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    			int res=mapper.deleteStudent(7);
    			sqlSession.commit();
    			System.out.println(res);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    
    }
    

6.2注解实现映射器(后续讲解)

7.全局配置文件

7.1 配置内容

主配置文件中的内容和顺序以下:

  属性
settings 全局配置参数
typeAliases 类型别名
typeHandlers 类型处理器,javaType<--->jdbcType类型之间的转换
objectFactory 对象工厂
plugins 能够在Mybatis执行SQL语句的流程中,横叉一脚去实现一些功能加强,好比PageHelper分页插件,就是第三方实现的一个插件
environments 环境集合属性对象,environment(环境子属性对象),transactionManager(事务管理),dataSource(数据源)
mappers 映射器
databaseIdProvider 数据库厂商标识

7.2 properties 标签(重点)

主配置文件能够引用java属性文件中的配置信息

  1. 在classpath下定义db.properties文件

     
  2. 在主配置文件中,引用db.properties中的属性,具体以下:

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:8888/msgdb
    username=root
    password=123456
    
  3. properties标签除了可使用resource属性,引用properties文件中的属性。还能够在properties标签内定义property子标签来定义属性和属性值,具体以下:

    <properties resource="db.properties">
        <property name="driver" value="com.mysql.cj.jdbc.Driver1"/>
     </properties>
    

注意:MyBatis 将按照下面的顺序来加载属性:

  • 读取properties 元素体内定义的属性。

  • 读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。

7.3 类型别名(typeAliases)

别名的做用:类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减小类彻底限定名的冗余。

  • 默认类型别名

别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator
  • 自定义别名

    • 单个别名定义

      <typeAliases>
        <typeAlias alias="user" type="com.hwua.entity.User"/>
      <typeAlias alias="message" type="com.hwua.entity.Message"/>
      </typeAliases>
      
    • 别名包扫描(重点)

      <typeAliases>
        <!-- 包扫描,把包中的类都自动区别名,名别的名字默认是小写的类名 -->
        <package name="com.hwua.entity"/>
       </typeAliases>
      
    • 当包扫描中一个别名对应多个同名类的时候,会产生冲突,存在二义性,报错,咱们能够经过注解来给类指定对应的别名来解决这个问题.

      @Alias("user2")
      public class User {
      	private Integer id;
      	private String name;
      	private String pwd;
      	private String email;
      

       

    • 注意:别名是不区分大小写的

7.4 映射器(mappers)

既然 MyBatis 的行为已经由上述元素配置完了,咱们如今就要定义 SQL 映射语句了。 可是首先咱们须要告诉 MyBatis 到哪里去找到这些语句。 Java 在自动查找这方面没有提供一个很好的方法,因此最佳的方式是告诉 MyBatis 到哪里去找映射文件。 你可使用相对于类路径的资源引用, 或彻底限定资源定位符(包括 file:/// 的 URL),或类名和包名等。例如:

  • 使用相对于类路径的资源引用

    <!-- 使用相对于类路径的资源引用 -->
    <mappers>
      <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
      <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
      <mapper resource="org/mybatis/builder/PostMapper.xml"/>
    </mappers>
    
  • 使用彻底限定资源定位符(URL)

    <!-- 使用彻底限定资源定位符(URL) -->
    <mappers>
      <mapper url="file:///var/mappers/AuthorMapper.xml"/>
      <mapper url="file:///var/mappers/BlogMapper.xml"/>
      <mapper url="file:///var/mappers/PostMapper.xml"/>
    </mappers>
    
  • 使用映射器接口实现类的彻底限定类名

    <!-- 使用映射器接口实现类的彻底限定类名 -->
    <mappers>
      <mapper class="org.mybatis.builder.AuthorMapper"/>
      <mapper class="org.mybatis.builder.BlogMapper"/>
      <mapper class="org.mybatis.builder.PostMapper"/>
    </mappers>
    
  • 将包内的映射器接口实现所有注册为映射器(重点)

    <!-- 将包内的映射器接口实现所有注册为映射器 -->
    <mappers>
      <package name="org.mybatis.builder"/>
    </mappers>
    

注意:第三第四种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

 

8.输入映射和输出映射

8.1 输入参数映射(parameterType)

parameterType属性能够映射的输入参数类型有:简单类型、POJO类型、Map类型、List类型(动态sql中讲)。

  • 输入多个参数的解决方法, 不要指定parameterType属性

    • 使用#{arg下标}直接取指定下标所对应参数的值,下标从0开始,可读性差

      <mapper namespace="com.hwua.mapper.MessageMapper">
        <select id="queryMsgByLimit" resultType="com.hwua.entity.Message" parameterType="com.hwua.entity.User">
           select id,sendid,title,msgcontent,state,receiveid,msg_create_date from messages where receiveid=#{arg0} order by msg_create_date desc limit #{arg1},#{arg2}
        </select>
      </mapper>
      

       

    • 使用#{param下标}直接取指定下标所对应参数的值,下标从1开始,可读性差

      <mapper namespace="com.hwua.mapper.MessageMapper">
        <select id="queryMsgByLimit" resultType="com.hwua.entity.Message" parameterType="com.hwua.entity.User">
           select id,sendid,title,msgcontent,state,receiveid,msg_create_date from messages where receiveid=#{param1} order by msg_create_date desc limit #{param2},#{param3}
        </select>
      </mapper>
      

       

    • 使用注解@param(" 参数名字")来指定sql语句中的占位符名字,可读性比较好,推荐使用(重点)

      public List<Message> queryMsgByLimit(@Param("receiveid")int receiveid,@Param("start")int start,@Param("pageSize")int pageSize) throws SQLException;
      
      <mapper namespace="com.hwua.mapper.MessageMapper">
        <select id="queryMsgByLimit" resultType="com.hwua.entity.Message" parameterType="com.hwua.entity.User">
           select id,sendid,title,msgcontent,state,receiveid,msg_create_date from messages where receiveid=#{receiveid} order by msg_create_date desc limit #{start},#{pageSize}
        </select>
      </mapper>
      
  • 入参使用map来实现多参数的传递

    public List<Message> queryMsg(Map<String, Object> map)throws SQLException;
    
     <select id="queryMsg" resultType="com.hwua.entity.Message" parameterType="map">
         <!--#{start} 是传入map对象中key的名字  -->
         select id,sendid,title,msgcontent,state,receiveid,msg_create_date from messages where receiveid=#{receiveid} order by msg_create_date desc limit #{start},#{pageSize}
      </select>
    

     

8.2 输出类型映射(resultType)

resultType属性能够映射的java类型有:简单类型、POJO类型、Map类型。

resultType结果为map类型:就是把一条记录封装成一个map对象.map的key指的是表的字段名,值就是表字段所对应的值(了解)

public Map<String,Object> findUserById(@Param("id")Integer id)throws SQLException;
public List<Map<String,Object>> findAllUsers()throws SQLException;

 <select id="findUserById" resultType="map" parameterType="int">
     select id,name,pwd,email from users where id=#{id}
  </select>
  
  <select id="findAllUsers" resultType="map">
     select id,name,pwd,email from users
  </select>

 

  • 注意:使用resultType进行输出映射时,要求sql语句中查询的列名和要映射的pojo的属性名一致。

  • 当sql语句中查询的列名和要映射的pojo的属性名不一致的时候如何完成映射?

    • 就是在查询字段的时候,给字段名取一个别名,让别名和pojo类中的属性名一致,会完成自动映射

       <select id="querUserById" resultType="user2" parameterType="int">
           select id,name as username,pwd,email from users where id = #{id}
        </select>
      

       

    • 使用resultMap来完成手动映射(就是人为的去指定记录中哪一个字段去映射pojo类中的哪一个属性)

8.3 输出类型映射(resultMap)(重点)

若是sql查询列名和pojo的属性名不一致,能够经过resultMap将列名和属性名做一个对应关系,最终将查询结果映射到指定的pojo对象中。resultType底层也是经过resultMap完成映射的

<select id="querUserById" resultMap="userMapper"
		parameterType="int">
		select id,name,pwd,email from users where id = #{id}
	</select>
	<!--结果映射 type:要映射成哪一个类型的对象 -->
	<resultMap type="user2" id="userMapper">
		<!--对表中的主键进行映射 -->
		<id property="id" column="id" />
		<result property="username" column="name" />
		<result property="pwd" column="pwd" />
		<result property="email" column="email" />
	</resultMap>

 

 

9.关联查询(重点)

- 多表查询,表与表之间存在相应的关系,1对1,1对多,多对对,关联查询的数据如何进行映射.关联查询是比较复杂的映射,通常使用resultMap来进行复杂映射

9.1 一对一查询

  • 直接联表查询的方式来实现一对一的关系

    <?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.hwua.mapper.TeacherMapper">
    	<select id="findAllTeacher" resultMap="teacherMapper">
    		select t.id
    		tid,t_name,sex,birthday,d.id did,dno,address from teacher t left
    		join
    		driverlicense d on did = d.id
    	</select>
    	<resultMap type="teacher" id="teacherMapper">
    		<id property="id" column="tid" />
    		<result property="t_name" column="t_name" />
    		<result property="sex" column="sex" />
    		<result property="birthday" column="birthday" />
    		<!--配置1对1的关系 -->
    		<association property="driverLicense"
    			javaType="driverLicense">
    			<id property="id" column="did" />
    			<result property="dno" column="dno" />
    			<result property="address" column="address" />
    		</association>
    	</resultMap>
    </mapper>
    
  • 分表查询的方式来实现1对1的关系(相似于子查询)

    <!--查询teacher表中的信息-->
    <select id="findAllTeacher" resultMap="teacherMapper">
    		select id,t_name,sex,birthday,did from teacher
    	</select>
    
    	<resultMap type="teacher" id="teacherMapper">
    		<id property="id" column="id" />
    		<result property="t_name" column="t_name" />
    		<result property="sex" column="sex" />
    		<result property="birthday" column="birthday" />
    		<!--column指的要传递个DriverLicense对象中的findDriverLicenseById中的参数  -->
    		<association property="driverLicense" javaType="DriverLicense" column="did"
    		 select="com.hwua.mapper.DriverLicenseMapper.findDriverLicenseById">
    		</association>
    	</resultMap>
    
    public interface TeacherMapper {
    	public List<Teacher> findAllTeacher() throws Exception;
    	public Teacher findTeacherById(Integer id) throws Exception;
    
    }
    	
    <!--查询驾照表的信息-->
    <mapper namespace="com.hwua.mapper.DriverLicenseMapper">
    	<select id="findDriverLicenseById" parameterType="int"
    		resultType="driverLicense">
    		select id,dno,address from driverlicense where id = #{id}
    	</select>
    </mapper>
    
    
    public interface DriverLicenseMapper {
    	//根据id来找到驾照信息
       DriverLicense findDriverLicenseById(Integer id) throws Exception;
    }
    
    

     

9.2 一对多查询

  • 第一种方式:多表查询实现

    <select id="findAllTeacher2" resultMap="teacherMapper2">
    		select t.id,t_name,sex,birthday,d.id did ,dno,address,c.id cid,cno,cname from teacher t left join driverlicense d on t.did = d.id left JOIN course c on t.id = c.tid
    	</select>
    	<resultMap type="teacher" id="teacherMapper2">
    		<id property="id" column="id" />
    		<result property="t_name" column="t_name" />
    		<result property="sex" column="sex" />
    		<result property="birthday" column="birthday" />
    		<association property="driverLicense" javaType="driverLicense">
    		  <id property="id" column="did"/>
    		  <result property="dno" column="dno" />
    		  <result property="address" column="address" />
    		</association>
    		<collection property="cList" javaType="list" ofType="course">
    		  <id property="id" column="cid"/>
    		  <result property="cno" column="cno" />
    		  <result property="cname" column="cname" />
    		</collection>
    	</resultMap>
    
  • 分表查询

    <!--配置一对多的关系  -->
    <collection property="cList" javaType="list" ofType="course" column="id"
    		select="com.hwua.mapper.CourseMapper.findCoursesById">
    </collection>
    
    <?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.hwua.mapper.CourseMapper">
    	<select id="findCoursesById" parameterType="int"
    		resultType="course">
    		select id,cno,cname from course where tid=#{id}
    	</select>
    </mapper>
    
    public interface CourseMapper {
    	public List<Course> findCoursesById(Integer id);
    }
    

     

9.3 多对多查询(不支持多对多)

10.延迟加载(重点)

  • 什么是延迟加载?

    • 就是当用到对象中的数据的时候,才把这个数据库从数据库中查找出来.

  • 设置延迟加载,在主配置文件中去开启延迟加载

    <!--全局配置  -->
    	<settings>
    	   <setting name="lazyLoadingEnabled" value="true"/><!--开启延迟加载  -->
    	   <setting name="aggressiveLazyLoading" value="true"/><!--开启层级加载  -->
    	</settings>
    	
    咱们能够在配置文件中设置fetchType 来覆盖全局配置文件中的lazyLoadingEnabled的设置
    <!--配置一对多的关系  -->
    <collection property="cList" javaType="list" ofType="course" column="id"
    	select="com.hwua.mapper.CourseMapper.findCoursesById" fetchType="lazy">
    </collection>
    

11.自定义类型转换器

需求:(须要,把int 转成 varchar,把1转换成男存入数据库,把2转换女存入数据库,其它状况把不肯定存入数据库)

  1. 建立一个类去继承BaseHandler,并实现其中的抽象方法

    package com.hwua.typehandler;
    
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.apache.ibatis.type.BaseTypeHandler;
    import org.apache.ibatis.type.JdbcType;
    
    public class IntegerTypeHandler extends BaseTypeHandler<Integer> {
    
    	// javaType--->JdbcType
    	@Override
    	public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)
    			throws SQLException {
    
    		if (parameter == 1) {
    			ps.setString(i, "男");
    		} else if (parameter == 2) {
    			ps.setString(i, "女");
    		} else {
    			ps.setString(i, "不肯定");
    		}
    	}
    
    	@Override
    	public Integer getNullableResult(ResultSet rs, String columnName) throws SQLException {
    		String res = rs.getString(columnName);
    		if(res.equals("男")) {
    			return 1;
    		}else if(res.equals("女")) {
    			return 2;
    		}else {
    			return 3;
    		}
    	}
    
    	@Override
    	public Integer getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    		String res = rs.getString(columnIndex);
    		if(res.equals("男")) {
    			return 1;
    		}else if(res.equals("女")) {
    			return 2;
    		}else {
    			return 3;
    		}
    	}
    
    	@Override
    	public Integer getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    		String res = cs.getString(columnIndex);
    		if(res.equals("男")) {
    			return 1;
    		}else if(res.equals("女")) {
    			return 2;
    		}else {
    			return 3;
    		}
    	}
    
    }
    
    
  2. 在全局配置文件中注册自定义的类型转换器到环境中

    <!--配置自定义类型转换器  -->
    <typeHandlers>
    	   <typeHandler handler="com.hwua.typehandler.IntegerTypeHandler" javaType="int" jdbcType="VARCHAR"/>
    </typeHandlers>
    
  3. 使用自定义类型转换器来进行转换

    <!--第一种使用方式:指定typeHandler-->
    <mapper namespace="com.hwua.mapper.UserMapper">
    	<select id="findAllUsers" resultMap="userMapper">
    	  select id,name,sex from user
    	</select>
    	
    	<resultMap type="user" id="userMapper">
    	  <id property="id" column="id"/>
    	  <result property="name" column="name"/>
    	  <result property="sex" column="sex" typeHandler="com.hwua.typehandler.IntegerTypeHandler"/>
    	</resultMap>
    	<insert id="saveUser" parameterType="user">
    	  insert into user values(null,#{name},#{sex,typeHandler=com.hwua.typehandler.IntegerTypeHandler})
    	</insert>
    </mapper>
    
    
    <!--第二种使用方式:指定javaType和jdbcType-->
    <?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.hwua.mapper.UserMapper">
    	<select id="findAllUsers" resultMap="userMapper">
    	  select id,name,sex from user
    	</select>
    	
    	<resultMap type="user" id="userMapper">
    	  <id property="id" column="id"/>
    	  <result property="name" column="name"/>
    	  <result property="sex" column="sex" javaType="int" jdbcType="VARCHAR"/>
    	</resultMap>
    	<insert id="saveUser" parameterType="user">
    	  insert into user values(null,#{name},#{sex,javaType=int,jdbcType=VARCHAR})
    	</insert>
    </mapper>
    

     

12.动态SQL(重点)

MyBatis 的强大特性之一即是它的动态 SQL。若是你有使用 JDBC 或其它相似框架的经验,你就能体会到根据不一样条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性能够完全摆脱这种痛苦。

12.1 if

<select id="findUser" resultMap="userMapper"
		parameterType="user">
		select id,name,sex from user where 1=1
		<if test="id!=null">
			and id = #{id}
		</if>
		<if test="name!=null">
			and name = #{name}
		</if>
		<if test="sex!=null">
			and sex = #{sex,javaType=int,jdbcType=VARCHAR}
		</if>
	</select>

 

12.2 choose(when,otherwise)

  • 相似于java中的多重if..else if...,也就是多个条件中只会知足一个,当前知足了后面就不会在判断.

    <select id="findUser" resultMap="userMapper"
    		parameterType="user">
    		select id,name,sex from user
    		<where>
    			<choose>
    				<when test="id!=null">
    					and id = #{id}
    				</when>
    				<when test="name!=null">
    					and name = #{name}
    				</when>
    				<otherwise>
    					and sex = #{sex,javaType=int,jdbcType=VARCHAR}
    				</otherwise>
    			</choose>
    		</where>
    	</select>
    

     

12.3 where

  • 添加where 关键字,并把仅跟在where后面的and 或者 or删除

    <select id="findUser" resultMap="userMapper"
    		parameterType="user">
    		select id,name,sex from user
    		<where>
    			<if test="id!=null">
    				and id = #{id}
    			</if>
    			<if test="name!=null">
    				and name = #{name}
    			</if>
    			<if test="sex!=null">
    				and sex = #{sex,javaType=int,jdbcType=VARCHAR}
    			</if>
    		</where>
    	</select>
    

     

12.4 set

  • 用于更新语句,去掉最后一个逗号

    <update id="updateUser" parameterType="user">
    	   update user
    	   <set>
    	     <if test="name!=null">
    	       name=#{name},
    	     </if>
    	     <if test="sex!=null">
    	       sex=#{sex,javaType=int,jdbcType=VARCHAR},
    	     </if>
    	   </set>
    	   where id=#{id}
    	</update>
    

     

12.5 trim

<update id="updateUser" parameterType="user">
		<!-- update user <set> <if test="name!=null"> name=#{name}, </if> <if test="sex!=null"> 
			sex=#{sex,javaType=int,jdbcType=VARCHAR}, </if> </set> where id=#{id} -->

		update user
		<trim prefix="set" suffixOverrides=",">
			<if test="name!=null">
				name=#{name},
			</if>
			<if test="sex!=null">
				sex=#{sex,javaType=int,jdbcType=VARCHAR},
			</if>
		</trim>
		where id=#{id}
	</update>
<select id="findUser" resultMap="userMapper"
		parameterType="user">
		select id,name,sex from user
		<trim prefix="where"  prefixOverrides="and|or">
			<if test="id!=null">
				and id = #{id}
			</if>
			<if test="name!=null">
				and name = #{name}
			</if>
			<if test="sex!=null">
				and sex = #{sex,javaType=int,jdbcType=VARCHAR}
			</if>
		</trim>
	</select>

 

12.6 foreach

public List<User> findUsers(List<Integer> list)throws Exception;

<select id="findUsers" resultMap="userMapper"
		parameterType="list">
		select id,name,sex from user where id in
		<foreach collection="list" item="item" open="(" separator=","
			close=")">
			#{item}
		</foreach>
</select>

12.7 sql片断

   <!--声明sql片断--> 
    <sql id="userfield">
	   id,name,sex 
	</sql>

	<select id="findAllUsers" resultMap="userMapper">
		select 
		 <!--根据id引入指定的sql片断-->
       <include refid="userfield"></include>
		from user
	</select>

 

13.MyBatis缓存(了解)

1. 一级缓存(自己自带开启了)

- 缓存的数据保存在SqlSession中,同一个SqlSession执行的相同的查询时,第一次从数据库查询,把查询的结果保存到sqlSession中,第二次执行相同查询的时候,直接从缓存中读取.
- 为了保证缓存中和数据库中数据的一致性,因此当sqlsession执行增删改,提交事务的操做的时候,会清空一级缓存中的数据

2. 二级缓存(默认是关闭的,通常也不推荐使用)--了解

  • 二级缓存的数据保存在SqlSessionFactory中,多个SqlSession查询的语句会共享二级缓存的数据,当其它SqlSession执行增删改查的时候都会清空二级缓存,放置数据出现脏读.

14.PageHelper分页插件(会用)

14.1 使用PageHelper步骤

  1. 下载jar包

    <dependency>
    	<groupId>com.github.pagehelper</groupId>
    	<artifactId>pagehelper</artifactId>
    	<version>5.1.2</version>
    </dependency>
    

     

  2. 配置PageHelper插件

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- config params as the following -->
            <property name="helperDialect" value="mysql"/>
    	</plugin>
    </plugins>
    
  3. 使用PageHelper实现分页功能

    package com.hwua.entity;
    
    public class Student {
    	private Integer id;
    
    	@Override
    	public String toString() {
    		return "Student [id=" + id + ", sno=" + sno + ", sname=" + sname + ", ssex=" + ssex + "]";
    	}
    
    	public Integer getId() {
    		return id;
    	}
    
    	public void setId(Integer id) {
    		this.id = id;
    	}
    
    	public String getSno() {
    		return sno;
    	}
    
    	public void setSno(String sno) {
    		this.sno = sno;
    	}
    
    	public String getSname() {
    		return sname;
    	}
    
    	public void setSname(String sname) {
    		this.sname = sname;
    	}
    
    	public String getSsex() {
    		return ssex;
    	}
    
    	public void setSsex(String ssex) {
    		this.ssex = ssex;
    	}
    
    	private String sno;
    	private String sname;
    	private String ssex;
    
    }
    
    
    package com.hwua.utils;
    
    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 SqlSessionFactoryUtils {
    	private static SqlSessionFactory sessionFactory = null;
    
    	//单例去建立SqlSessionFactory
    	private static SqlSessionFactory getInstance() throws Exception {
    		if (sessionFactory == null) {
    			synchronized (SqlSessionFactoryUtils.class) {
    				if (sessionFactory == null) {
    					sessionFactory = new SqlSessionFactoryBuilder()
    							.build(Resources.getResourceAsStream("mybatis-config.xml"));
    				}
    			}
    		}
    		return sessionFactory;
    	}
    
    	//获得SqlSession
    	public static SqlSession getSqlSession() throws Exception {
    		SqlSessionFactory sqlSessionFactory = getInstance();
    		return sqlSessionFactory.openSession();
    	}
    }
    
    
    package com.hwua.mapper;
    import java.util.List;
    import com.hwua.entity.Student;
    public interface StudentMapper {
    	public List<Student> findStudents();//查询全部的学生信息
    
    }
    
    <?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.hwua.mapper.StudentMapper">
    	<select id="findStudents" resultType="student">
    		select id,sno,sname,ssex from student
    	</select>
    </mapper>
    
    package com.hwua.service;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    import com.hwua.entity.Student;
    import com.hwua.mapper.StudentMapper;
    import com.hwua.utils.SqlSessionFactoryUtils;
    
    public class StudentService {
    	// 第一个参数第几页,第二个每页要显示的记录数
      public List<Student> findStudentsByPage(Integer page,Integer pageSize) throws Exception{
    	  SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
    	  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    	  //使用PageHelper的静态方法来设置分页参数
    	  PageHelper.startPage(page, pageSize);//这句话必须放在执行业务以前
    	  List<Student> stuList = mapper.findStudents();
    	  PageInfo<Student> pageInfo = new PageInfo<>(stuList);
    	  System.out.println("当前页:"+pageInfo.getPageNum());//获得当前页
    	  System.out.println("总页数:"+pageInfo.getPages());//获得总页数
    	  System.out.println("总记录数:"+pageInfo.getTotal());//表中的总记录数
    	  System.out.println("下一页:"+pageInfo.getNextPage());
    	  System.out.println("上一页:"+pageInfo.getPrePage());
    	  System.out.println("全部导航页号:"+pageInfo.getNavigatepageNums());//
    	  System.out.println("导航条上的第一页:"+pageInfo.getNavigateFirstPage());
    	  System.out.println("导航条上的最后一页:"+pageInfo.getNavigateLastPage());
    	  List<Student> list = pageInfo.getList();//当前页所获得的记录的集合
    	  return list;
      }
    }
    
    
    package com.hwua.test;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.hwua.entity.Student;
    import com.hwua.service.StudentService;
    import com.hwua.utils.SqlSessionFactoryUtils;
    
    public class StudentTest {
    	@Test
    	public void testFindStudentByPage() {
    		SqlSession sqlSession = null;
    		try {
    			sqlSession = SqlSessionFactoryUtils.getSqlSession();
    			StudentService stuService = new StudentService();
    			List<Student> stuList = stuService.findStudentsByPage(2, 3);
    			for(Student stu:stuList) {
    				System.out.println(stu);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (sqlSession != null) {
    				sqlSession.close();
    			}
    		}
    	}
    }
    

15.注解开发(了解)

相关文章
相关标签/搜索