JavaEE三大框架——Mybatis基础入门

Mybatis

历史:ibatis–>mybatis(3.0–>版本)
半自动、持久层框架(ORM对象关系映射)
核心对象:SqlSessionFactory–>SqlSession(Connection)
全局配置文件:环境、mapper对象引入
Mapper配置文件:实现功能的核心
Namespace:绑定接口地址
id:方法名(通过Namespace+id来唯一定位你声明的方法)
注意:同一接口中,方法不能重载
标签的写法:
1、参数的注入:入参为实体类:#(属性名)
2、入参为一个参数:#(参数名)
3、入参为多个参数,系统底层为每个参数默认的名称为(arg0,arg1或者是parm1,parm2),但这种可读性较弱,通常配合注解@Param
结果集的包装:
1、默认的结果集包装:resultType:需要具体指定数据类型的具体位置(全路径),或者取别名,这种数据类型缺陷:如果属性和字段不匹配,会造成结果无法注入
2、如何解决属性和字段冲突:(1)将数据库字段与属性设为一致(2)为sql语句查询的字段取别名(3)采用resultMap标签

  • 安装

要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于 classpath 中即可。
如果使用 Maven 来构建项目,则需将下面的 dependency 代码置于 pom.xml 文件中:
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

  • 从 XML 中构建 SqlSessionFactory

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。
从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。但是也可以使用任意的输入流(InputStream)实例,包括字符串形式的文件路径或者 file:// 的 URL 形式的文件路径来配置。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,可使从 classpath 或其他位置加载资源文件更加容易。
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
XML 配置文件(configuration XML)中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。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>

<typeAliases>
<!-- 取别名 -->
<typeAlias type="com.hqyj.mybatis.Blog" alias="Blog"/>
</typeAliases>

  <environments default="development">
  <!-- 配置环境 -->
    <environment id="development">
      <transactionManager type="JDBC"/>
      <!-- 事务管理 -->
      <dataSource type="POOLED">
      <!-- 数据源 -->
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  
  <mappers>
  <!-- 映射器 -->
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

注意这里的关键点:

默认的环境 ID(比如:default=“development”)。
每个 environment 元素定义的环境 ID(比如:id=“development”)。
事务管理器的配置(比如:type=“JDBC”)。
数据源的配置(比如:type=“POOLED”)。
默认的环境和环境 ID 是自解释的,因此一目了然。你可以对环境随意命名,但一定要保证默认的环境 ID 要匹配其中一个环境 ID。
事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):
JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:
<transactionManager type="MANAGED">
  <property name="closeConnection" value="false"/>
</transactionManager>
提示:如果你正在使用== Spring + MyBatis,则没有必要配置事务管理器, 因为 Spring 模块会使用自带的管理器来覆盖前面的配置。
数据源(dataSource)
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
许多 MyBatis 的应用程序会按示例中的例子来配置数据源。虽然这是可选的,但为了使用延迟加载,数据源是必须配置的。
有三种内建的数据源类型(也就是 type=”[UNPOOLED|POOLED|JNDI]”):
UNPOOLED– 每次都要建立连接,连接后都会断开,下次再访问时又会再次建立连接 不同的数据库在性能方面的表现也是不一样的,对于某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性:
driver – 这是 JDBC 驱动的 Java 类的完全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
url – 这是数据库的 JDBC URL 地址。
username – 登录数据库的用户名。
password – 登录数据库的密码。
defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
作为可选项,你也可以传递属性给数据库驱动。要这样做,属性的前缀为“driver.”,例如:
driver.encoding=UTF8
这将通过 DriverManager.getConnection(url,driverProperties) 方法传递值为 UTF8 的 encoding 属性给数据库驱动。
POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。
(相当于建立连接后就放进一个容器里,每次访问时就从里面拿,不用再次建立连接)
除了上述提到 UNPOOLED 下的属性外,还有更多属性用来配置 POOLED 的数据源:
poolMaximumActiveConnections – 在任意时间可以存在的活动(也就是正在使用)连接数量,默认值:10
poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
poolTimeToWait – 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直安静的失败),默认值:20000 毫秒(即 20 秒)。
poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程. 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过 poolMaximumIdleConnections 与 poolMaximumLocalBadConnectionTolerance 之和。 默认值:3 (新增于 3.4.5)
poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。
poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。
poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。
JNDI – 这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
这种数据源配置只需要两个属性:
initial_context – 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。
这是个可选属性,如果忽略,那么 data_source 属性将会直接从 InitialContext 中寻找。

data_source – 这是引用数据源实例位置的上下文的路径。
提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。
和其他数据源配置类似,可以通过添加前缀“env.”直接把属性传递给初始上下文。比如:
env.encoding=UTF8
这就会在初始上下文(InitialContext)实例化时往它的构造方法传递值为 UTF8 的 encoding 属性。

  • 映射器(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) -->
<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 XML 文件

MyBatis 的真正强大在于它的映射语句,MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。

blog表

idtitlecontent
1aaa1111
2aaa1111
3bbb2222
4bbb3333

注:由于演示代码需要,表中的数据不定

SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
cache – 给定命名空间的缓存配置。
cache-ref – 其他命名空间缓存配置的引用。
resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
~~parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。~~
sql – 可被其他语句引用的可重用语句块。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语句

老版本mybatis的操作形式

Mapper 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">
  
  <!-- namespace:名称空间 -->
<mapper namespace="org.mybatis.example.BlogMapper"><!--Java通过这个名称空间来找唯一标识的SQL方法-->
<!-- id:唯一标识
	resultType:返回结果对象类型
	#{id}:参数
 -->
  <select id="selectBlog" resultType="Blog">
    select * from blog where id = #{id}
  </select>
  
<!--   <insert id="insertBlog">
  insert into blog (title,content)
  values (#{title},#{content})
	</insert> -->

</mapper>
Java文件
/**
 * 
 * <p>
 * 1、导包(mybatis的支持,mysql数据库的支持)
 * 2、编写了一个mybatis-config.xml(全局配置文件),主要包含数据库访问信息
 * 3、创建mybatis的核心对象SqlSessionFactory产生sqlsession-->connection
 * 4、数据映射文件(编写sql脚本,对象关系映射)
 * 5、在全局配置文件中,引入该数据映射文件
 * 
 * </p>	
 * @Copyright (C),华清远见
 * @author HC
 * @Date:2018年11月19日
 */
public class MybatisDemo {
	/**
	 * 
	 * <p>
	 * 老版本mybatis的操作形式
	 * </p>
	 * @author zlf
	 * @Date 2018年11月19日
	 * @throws IOException
	 */
	public void test01() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		//这里的Blog是自创的对象
		try {
		  //名称空间加上要调用的方法的id来调用,返回一个Blog对象
		  Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 1);
		  System.out.println(blog);
		  
		  
//		  Blog b = new Blog();
//		  b.setTitle("dadsadsd");
//		  b.setContent("sdsadsad");
//		  session.insert("org.mybatis.example.BlogMapper.insertBlog", b);
//		  session.commit();
		} finally {
		  session.close();//每次都需要关闭
		}
	}
}	
结果
Blog [id=1, title=我的博客, content=博客内容]

面向接口的mybatis

BlogDao接口文件
    package com.hqyj.dao;

    import java.util.List;
    
    import org.apache.ibatis.annotations.Param;

    import com.hqyj.mybatis.Blog;

    public interface BlogDao {
        //根据id查询
     	public Blog findByid(Integer id);
     	//传入对象修改记录
    	public void update(Blog blog);
    	//传入对象增加记录
    	public void insert(Blog blog);
    	//传入对象删除记录
    	public void delete(Blog blog);
    	//查找所有记录
    	public List<Blog> finaAll();
	    
	    //传入多种参数,第一种方式,直接传参,在Mapper XML文件中去用arg0,arg1去指定参数
    	public List<Blog> findByids(Integer id,Integer id2);
    	
    	//传入多种参数,指定参数的引用,在Mapper XML文件中使用引用的名字去指定参数
    	public List<Blog> findByidsAnnoation(@Param("id")Integer id,@Param("id2")Integer id2);
}

Mapper 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">
  
  <!-- namespace:名称空间 :面向接口编程的时候,必须为接口所在位置 -->
<mapper namespace="com.hqyj.dao.BlogDao">


  <!-- resultMap:结果映射的配置标签,引用了这个标签就不用再声明单个返回类型resultType
  		type:封装的结果类型
  		column:数据库中的字段
  		property:属性
  		id:引用结果映射的唯一标识
   -->
  <resultMap type="Blog" id="blogmap">
	<result column="id" property="id"/>  
	<result column="title" property="title"/>  
	<result column="content" property="content"/>  
  </resultMap>




<!-- id:唯一标识 :面向接口编程的时候,id为方法名
	resultType:返回结果对象类型
	#{id}:参数
	mybatis 里不支持接口函数的重载,因为id是唯一标识
 -->
 
 <!--面向接口编程的时候,id为方法名-->
 <!--查询方法就是select标签-->
  <select id="findByid" resultMap="blogmap">
    select * from blog where id = #{arg0}
  </select>
  
  <!--更新方法就是update标签-->
  <update id="update">
  	update blog set title=#{title},content=#{content} where id=#{id}
  </update>
  
  <!--增加方法就是insert标签-->
  <insert id="insert">
  	insert INTO blog(title,content) VALUES(#{title},#{content})
  
  </insert>
  
  <!--删除方法就是delete标签-->
  <delete id="delete">
  	DELETE FROM blog where id = #{id}
  </delete>
  
  <!--查询所有返回的List对象,同样可以使用resultMap结果映射来返回,它又底层返回的单个对象一一组成-->
  <select id="finaAll"  resultMap="blogmap">
  	 select * from blog
  </select>
  
  
  <!-- 方法传入多个参数的情况下,参数名并非按照方法中定义的参数名来获取,默认底层在arg0,arg1来实现 -->
  <select id="findByids" resultMap="blogmap">
 	 select * from blog where id = #{arg0} or id= #{arg1}
  </select>
  
  <!-- 在接口方法中指定了参数的引用@Param,直接使用引用来指定参数 -->
  <select id="findByidsAnnoation" resultMap="blogmap">
  	select * from blog where id = #{id} or id= #{id2}
  </select>
  
</mapper>
Java文件
package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;

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.Test;

import com.hqyj.dao.BlogDao;
import com.hqyj.dao.BlogDaoAnnotation;
/**
 * 
 * <p>
 * 1、导包(mybatis的支持,mysql数据库的支持)
 * 2、编写了一个mybatis-config.xml(全局配置文件),主要包含数据库访问信息
 * 3、创建mybatis的核心对象SqlSessionFactory产生sqlsession-->connection
 * 4、数据映射文件(编写sql脚本,对象关系映射)
 * 5、在全局配置文件中,引入该数据映射文件
 * 
 * </p>	
 * @Copyright (C),华清远见
 * @author HC
 * @Date:2018年11月19日
 */
public class MybatisDemo {

//手动提交,因为调用了事务,所以增删改需要调用commit()方法手动提交
//			session.commit();
//可以往commit()方法里传boolean类型的参数来设置提交
//			session.commit(true);
//			session.commit(false);







	/**
	 * 
	 * <p>
	 *   面向接口形式
	 * </p>
	 * @author zlf
	 * @Date 2018年11月19日
	 * @throws IOException
	 */
	@Test
	public void test02() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		
		try {
		//无需再写实现类,直接得到这个类class的映射作为代理映射
			BlogDao dao = session.getMapper(BlogDao.class);
				/**
            	 * 使用代理映射去调用方法,因为接口中的方法名和Mapper XML文件中的id对应
            	 * 所以会去Mapper XML文件中直接调用id为方法名的SQL
            	 */
			System.out.println(dao.findByid(1));
			
		}finally {
			session.close();
		}
	}
	
	
	/**
	 * 
	 * <p>
	 *  注解的使用
	 * </p>
	 * @author zlf
	 * @Date 2018年11月19日
	 * @throws IOException
	 */
        
        
//    public interface BlogDaoAnnotation {
	//注解,直接在方法上面加注解,在代理实现去调用
//	@Select("select * from blog where id = #{id}")
//	public Blog findByidAnnotation(Integer id);

//}    
    	
	@Test
	public void test03() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		
		try {
			BlogDaoAnnotation dao = session.getMapper(BlogDaoAnnotation.class);
			System.out.println(dao.findByidAnnotation(1));
			
		}finally {
			session.close();
		}
	}
	
	
	
	/**
	 	当Java实体类属性字段和数据库字段不匹配
	 * 1、将数据库字段和Java实体类属性保持一致
	 * 2、强行将数据库查询的字段改名为Java的实体类属性
	 * 3、引用mybatis中标签<resultMap>--->结果集的包装
	 */
	
	
	/**
	 * 
	 * <p>
	 *  修改操作
	 * </p>
	 * @author zlf
	 * @Date 2018年11月19日
	 * @throws IOException
	 */
	@Test
	public void testUpdate() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		
		try {
			//获取dao接口的代理对象(实现类)
			BlogDao dao = session.getMapper(BlogDao.class);
			//Blog修改
			Blog blog = new Blog();
			blog.setId(4);
			blog.setTitle("333");
			blog.setContent("444");
			dao.update(blog);
			//手动提交,因为调用了事务,所以增删改需要手动提交
			session.commit();
			
		}finally {
			session.close();
		}
	}
	
	
	/**
	 * 
	 * <p>
	 *  增加操作
	 * </p>
	 * @author zlf
	 * @Date 2018年11月19日
	 * @throws IOException
	 */
	@Test
	public void testInert() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		
		try {
			//获取dao接口的代理对象(实现类)
			BlogDao dao = session.getMapper(BlogDao.class);
			//Blog修改
			Blog blog = new Blog();
			blog.setTitle("555");
			blog.setContent("666");
			dao.insert(blog);
			//手动提交,因为调用了事务,所以增删改需要手动提交
			session.commit();
			
		}finally {
			session.close();
		}
	}
	
	
	/**
	 * 
	 * <p>
	 *  删除操作
	 * </p>
	 * @author zlf
	 * @Date 2018年11月19日
	 * @throws IOException
	 */
	@Test
	public void testDelete() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		
		try {
			//获取dao接口的代理对象(实现类)
			BlogDao dao = session.getMapper(BlogDao.class);
			//Blog修改
			Blog blog = new Blog();
			blog.setId(10);
			dao.delete(blog);
			//手动提交,因为调用了事务,所以增删改需要手动提交
			session.commit();
			
		}finally {
			session.close();
		}
	}
	
	
	/**
	 * 
	 * <p>
	 *  查询所有操作
	 * </p>
	 * @author zlf
	 * @Date 2018年11月19日
	 * @throws IOException
	 */
	@Test
	public void testFindAll() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		
		try {
			//获取dao接口的代理对象(实现类)
			BlogDao dao = session.getMapper(BlogDao.class);
			//Blog修改
			System.out.println(dao.finaAll());
			
		}finally {
			session.close();
		}
	}
	
	/**
	 * 
	 * <p>
	 *  查询多个参数操作
	 * </p>
	 * @author zlf
	 * @Date 2018年11月19日
	 * @throws IOException
	 */
	@Test
	public void testFindids() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		
		try {
			//获取dao接口的代理对象(实现类)
			BlogDao dao = session.getMapper(BlogDao.class);
			//Blog修改
			System.out.println(dao.findByids(1,4));
			
		}finally {
			session.close();
		}
	}
	/**
	 * 
	 * <p>
	 *  查询多个参数操作
	 * </p>
	 * @author zlf
	 * @Date 2018年11月19日
	 * @throws IOException
	 */
	@Test
	public void testFindidsAnnoation() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		
		try {
			//获取dao接口的代理对象(实现类)
			BlogDao dao = session.getMapper(BlogDao.class);
			//Blog修改
			System.out.println(dao.findByidsAnnoation(1, 4));
			
		}finally {
			session.close();
		}
	}
	
}

  • Mybatis一对一关系查询

表中数据

学生表
idstudentnamet_idc_id
1张三11
2李四11
教师表
idteachername
1王麻子
2赵六
班级表
idclassname
1一年级一班
2一年级二班
分别建立老师,学生,班级的类,实现get、set方法,重写toString方法

Student.java

package com.hqyj.onetone.bean;

public class Student {
	private int id;
	private String studentname;
	private Teacher teacher;
......
}

Teacher.java

package com.hqyj.onetone.bean;

public class Teacher {
	private int id;
	private String teachername;
......
}

Classroom.java

package com.hqyj.onetomany.bean;

import java.util.List;

import com.hqyj.onetone.bean.Student;

public class Classroom {
	private int id;
	private String classname;
	private List<Student> students;
......
}

StudentDao.java

package com.hqyj.dao.StudentDao;

import java.util.List;

import com.hqyj.onetone.bean.Student;

public interface StudentDao {
    //根据id查,未使用标签与使用association用的方法
	public Student findByid(Integer id);
	//根据id查,分步查询
	public Student findByStepid(Integer id);
	
	//多对多,根据班级查询有哪些学生
	public List<Student> findByClassid(Integer id);
}

TeacherDao

package com.hqyj.dao.StudentDao;

import com.hqyj.onetone.bean.Teacher;

public interface TeacherDao {
//根据id查老师,分步查询中使用
	public Teacher findByid(Integer id);
}

ClassRoomDao

package com.hqyj.dao.onetomany;

import com.hqyj.onetomany.bean.Classroom;

public interface ClassRoomDao {
//根据id查
	public Classroom findByid(Integer id);
//分步多对多
	public Classroom findsetpByid(Integer id);
}
第一种、未使用其他标签的一对一查询

映射中的sql.xml文件(StudentDao)

<?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">
  
  <!-- namespace:名称空间 :面向接口编程的时候,必须为接口所在位置 -->
<mapper namespace="com.hqyj.dao.StudentDao.StudentDao">

<select id="findByid" resultMap="studentmap">
	select student.id sid,studentname,teacher.id tid,teachername from student,teacher where student.id=#{id} and student.t_id = teacher.id
</select>


<!-- 未使用标签实现结果包装 
	使用对象.属性的形式把数据库对象赋值给对象属性
-->
<resultMap type="com.hqyj.onetone.bean.Student" id="studentmap">
	<result property="id" column="sid"/>
	<result property="studentname" column="studentname"/>
	<result property="teacher.id" column="tid"/><!--直接赋值-->
	<result property="teacher.teachername" column="teachername"/>

</resultMap>
	
</mapper>

测试类

package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;

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.Test;

import com.hqyj.dao.StudentDao.StudentDao;

public class OneToOneTest {
	/**
	 * 
	 * <p>
	 * 未使用association标签
	 * </p>
	 * @author zlf
	 * @throws IOException 
	 * @Date 2018年11月20日
	 */
	@Test
	public void test01() throws IOException {
		//装载mybatis配置文件
				String resource = "mybatis-config.xml";
				InputStream inputStream = Resources.getResourceAsStream(resource);
				SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
				
				SqlSession session = sqlSessionFactory.openSession();
				
				try {
					//获取dao接口的代理对象(实现类)
					StudentDao dao = session.getMapper(StudentDao.class);
//					//一步查询
    				System.out.println(dao.findByid(1));
					
				}finally {
					session.close();
				}
	}
	
}

结果
Student [id=1, studentname=张三, teacher=Teacher [id=1, teachername=王麻子]]

第二种、使用association标签的一对一查询

映射中的sql.xml文件(StudentDao)

<?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">
  
  <!-- namespace:名称空间 :面向接口编程的时候,必须为接口所在位置 -->
<mapper namespace="com.hqyj.dao.StudentDao.StudentDao">

<select id="findByid" resultMap="studentflamap"><!--这里调用的是studentflamap,与上一个不一样-->
	select student.id sid,studentname,teacher.id tid,teachername from student,teacher where student.id=#{id} and student.t_id = teacher.id
</select>

<!-- 使用association标签引用实体对象 
	property="teacher" 赋值给那个属性,也可以是对象,这里student类中包装了teacher这个属性
	javaType="com.hqyj.onetone.bean.Teacher" 返回对象的路径
-->
<resultMap type="com.hqyj.onetone.bean.Student" id="studentflamap">
	<result property="id" column="sid"/>
	<result property="studentname" column="studentname"/>
	
	<association property="teacher" javaType="com.hqyj.onetone.bean.Teacher">
		<result property="id" column="tid"/>
		<result property="teachername" column="teachername"/>
	</association>

</resultMap>
	
</mapper>

测试类

package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;

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.Test;

import com.hqyj.dao.StudentDao.StudentDao;

public class OneToOneTest {
	/**
	 * 
	 * <p>
	 * 使用association标签
	 * </p>
	 * @author zlf
	 * @throws IOException 
	 * @Date 2018年11月20日
	 */
	@Test
	public void test01() throws IOException {
		//装载mybatis配置文件
				String resource = "mybatis-config.xml";
				InputStream inputStream = Resources.getResourceAsStream(resource);
				SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
				
				SqlSession session = sqlSessionFactory.openSession();
				
				try {
					//获取dao接口的代理对象(实现类)
					StudentDao dao = session.getMapper(StudentDao.class);
    				System.out.println(dao.findByid(1));
					
				}finally {
					session.close();
				}
	}
	
}

结果一样
Student [id=1, studentname=张三, teacher=Teacher [id=1, teachername=王麻子]]

第三种、使用association标签,分步查询,先查什么,再查什么

映射中的sql.xml文件(StudentDao)

<?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">
  
  <!-- namespace:名称空间 :面向接口编程的时候,必须为接口所在位置 -->
<mapper namespace="com.hqyj.dao.StudentDao.StudentDao">
<!-- 分步查询 
	1、根据学生的id查询教师的id
	2、根据教师的id查询教师的所有信息
-->
<select id="findByStepid" resultMap="studentstepmap">
	select * from student where id=#{id}

</select>

<!-- 
	select:调用其他方法
	column:利用已查询字段进行查询
	fetchType="lazy" 懒加载  当要使用的时候才加载
	fetchType="eager" 全加载  不管是否使用,都会加载
 -->

<resultMap type="com.hqyj.onetone.bean.Student" id="studentstepmap">
	<result property="id" column="id"/>
	<result property="studentname" column="studentname"/>
	<association property="teacher" select="com.hqyj.dao.StudentDao.TeacherDao.findByid" column="t_id" fetchType="lazy"></association>
</resultMap>
	
</mapper>

映射中的sql.xml文件(TeacherDao)

<?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">
  
  <!-- namespace:名称空间 :面向接口编程的时候,必须为接口所在位置 -->
<mapper namespace="com.hqyj.dao.StudentDao.StudentDao">
	<select id="findByid" resultType="com.hqyj.onetone.bean.Teacher">
		select * from teacher where id=#{id}
	</select>
	
</mapper>

测试类

package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;

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.Test;

import com.hqyj.dao.StudentDao.StudentDao;

public class OneToOneTest {
	/**
	 * 
	 * <p>
	 * 使用association标签
	 * </p>
	 * @author zlf
	 * @throws IOException 
	 * @Date 2018年11月20日
	 */
	@Test
	public void test01() throws IOException {
		//装载mybatis配置文件
				String resource = "mybatis-config.xml";
				InputStream inputStream = Resources.getResourceAsStream(resource);
				SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
				
				SqlSession session = sqlSessionFactory.openSession();
				
				try {
					//获取dao接口的代理对象(实现类)
					StudentDao dao = session.getMapper(StudentDao.class);
					//分步查询
    				System.out.println(dao.findByStepid(1));
					
				}finally {
					session.close();
				}
	}
	
}

结果一样
Student [id=1, studentname=张三, teacher=Teacher [id=1, teachername=王麻子]]

  • Mybatis一对多关系查询

沿用上几张表

第一种、使用connection标签一步查询

映射中的sql.xml文件(ClassRoomDao)

<?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">
  
  <!-- namespace:名称空间 :面向接口编程的时候,必须为接口所在位置 -->
<mapper namespace="com.hqyj.dao.onetomany.ClassRoomDao">

  <select id="findByid" resultMap="classroommap">
    select student.id sid,studentname,classroom.id cid,classname from student,classroom where student.c_id = classroom.id and classroom.id=#{id}
  </select>
  
  <!-- collection标签
  		property:返回的属性
  		ofType:所属对象
   -->
  <resultMap type="com.hqyj.onetomany.bean.Classroom" id="classroommap">
  	<result property="id" column="cid"/>
  	<result property="classname" column="classname"/>
  	<collection property="students" ofType="com.hqyj.onetone.bean.Student" >
  		<result property="id" column="sid"/>
  		<result property="studentname" column="studentname"/>
  	
  	</collection>
  
  </resultMap>

</mapper>

测试类

package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;

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.Test;

import com.hqyj.dao.StudentDao.StudentDao;
import com.hqyj.dao.onetomany.ClassRoomDao;

public class OneToMany {

	@Test
	public void test01() throws IOException {
		//装载mybatis配置文件
				String resource = "mybatis-config.xml";
				InputStream inputStream = Resources.getResourceAsStream(resource);
				SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
				
				SqlSession session = sqlSessionFactory.openSession();
				
				try {
					//获取dao接口的代理对象(实现类)
					ClassRoomDao dao = session.getMapper(ClassRoomDao.class);
					使用connection标签一步搞定
					System.out.println(dao.findByid(1));

					
				}finally {
					session.close();
				}
	}
	
}

结果
Classroom [id=1, classname=一年级一班, students=[Student [id=1, studentname=张三, teacher=null], Student [id=2, studentname=李四, teacher=null]]]

第二种、使用connection标签分步查询

映射中的sql.xml文件(ClassRoomDao)

<?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">
  
  <!-- namespace:名称空间 :面向接口编程的时候,必须为接口所在位置 -->
<mapper namespace="com.hqyj.dao.onetomany.ClassRoomDao">

   <!-- 分步查询 
  		1、根据教师编号,查询教室相关信息
  		2、根据教师编号,查询教室下所有学生
  -->
  <select id="findsetpByid" resultMap="classroomstepmap">
  	select * from classroom where id = 1;
  </select>
  
  <resultMap type="com.hqyj.onetomany.bean.Classroom" id="classroomstepmap">
  	<result property="id" column="id"/>
  	<result property="classname" column="classname"/>
  	
  	<collection property="students" column="id" select="com.hqyj.dao.StudentDao.StudentDao.findByClassid">
  		
  	</collection>
  	
  </resultMap>

</mapper>

映射中的sql.xml文件(StudentDao)

<select id="findByClassid" resultType="com.hqyj.onetone.bean.Student">
	select id,studentname from student where c_id=#{id}
</select>

测试类

package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;

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.Test;

import com.hqyj.dao.StudentDao.StudentDao;
import com.hqyj.dao.onetomany.ClassRoomDao;

public class OneToMany {

	@Test
	public void test01() throws IOException {
		//装载mybatis配置文件
				String resource = "mybatis-config.xml";
				InputStream inputStream = Resources.getResourceAsStream(resource);
				SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
				
				SqlSession session = sqlSessionFactory.openSession();
				
				try {
					//获取dao接口的代理对象(实现类)
					ClassRoomDao dao = session.getMapper(ClassRoomDao.class);
//					使用分步
					System.out.println(dao.findsetpByid(1));

					
				}finally {
					session.close();
				}
	}
	
}

结果一样
Classroom [id=1, classname=一年级一班, students=[Student [id=1, studentname=张三, teacher=null], Student [id=2, studentname=李四, teacher=null]]]


  • 动态SQL

BlogDao.java

package com.hqyj.dao.dynamicsql;

import java.util.List;

import com.hqyj.mybatis.Blog;

public interface BlogDao {
    //使用动态if
	public List<Blog> find(Blog blog);
	//使用trim标签补全where
	public List<Blog> find_where(Blog blog);
	//使用foreach查询多个记录
	public List<Blog> find_foreach(List<Integer> list);
	
}

映射文件的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">
  
  <!-- namespace:名称空间 :面向接口编程的时候,必须为接口所在位置 -->
<mapper namespace="com.hqyj.dao.dynamicsql.BlogDao">
<!-- if标签:类似于Java中的if语句,仅仅将sql拼凑到指定的sql语句中 
	choose标签:里面包裹when if otherwise 与Java中if else相似
	where 1=1 避免SQL语句拼接错误
-->
	<select id="find" resultMap="blogmap">
		select * from blog where 1=1
		
		<choose>
			<when test="id==0">
				<if test="title!=null">
					and title = #{title}
				</if>
				<if test="content!=null">
					and content = #{content}
				</if>
			</when>
			<otherwise>
				and id=#{id}
			</otherwise>
			
		
		</choose>
		
	</select>
	<!-- trim标签 避免使用where 1= 1  自动添加where和添加或取消and|or -->
	<select id="find_where" resultMap="blogmap">
		select * from blog 
		<trim prefix="where" prefixOverrides="and|or">
			<if test="title!=null">
				title = #{title}
			</if>
			<if test="content!=null">
				and content = #{content}
			</if>
		</trim>
	
	</select>
	
	<!-- 
		foreach标签  查询多个记录 
		collection :要遍历的集合
		open:从哪开始
		close:从哪结束
		separator:以什么分隔
		item:每一个的变量
		
		-->
	<select id="find_foreach" resultMap="blogmap">
		select * from blog
		<trim prefix="where" prefixOverrides="and|or">
			<if test="list!=null">
				and id in
				<foreach collection="list" open="(" close=")" item="blogid" separator=",">
					#{blogid}
				</foreach>
			
			</if>
		
		</trim>
	
	
	</select>
	
	
	
  
  	<resultMap type="com.hqyj.mybatis.Blog" id="blogmap">
  		<result column="id" property="id"/>  
		<result column="title" property="title"/>  
		<result column="content" property="content"/>  
  		
  	</resultMap>
  
</mapper>

测试类

package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;
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.Test;

import com.hqyj.dao.dynamicsql.BlogDao;



/**
 * 
 * <p>
 * 	动态SQL
 * </p>	
 * @Copyright (C),华清远见
 * @author HC
 * @Date:2018年11月20日
 */
public class DynamicSql {
	
	
	@Test
	public void testif() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		try {
		  BlogDao dao = session.getMapper(BlogDao.class);
		  Blog blog = new Blog();
		  blog.setTitle("aaa");
		  blog.setContent("444");
		  blog.setId(1);
		  System.out.println(dao.find(blog));
		  System.out.println(dao.find_where(blog));
		  
		  List<Integer> list = new ArrayList<>();
		  list.add(1);
		  list.add(4);
		  list.add(8);
		  list.add(9);
		  dao.find_foreach(list);
		  
		} finally {
		  session.close();
		}
	}
	
}

结果
[Blog [id=1, title=aaa, content=11111111111]]
[Blog [id=4, title=aaa, content=444]]
[Blog [id=1, title=aaa, content=11111111111], Blog [id=4, title=aaa, content=444], Blog [id=8, title=aaa, content=222], Blog [id=9, title=bbb, content=666]]


  • 懒加载与全加载

fetchType="lazy" 懒加载  当要使用到这个字段的时候才加载
fetchType="eager" 全加载  不管是否使用,都会加载
<association property="teacher" select="com.hqyj.dao.StudentDao.TeacherDao.findByid" column="t_id" fetchType="lazy"></association>

也可以在全局文件中直接设置

<!--系统设置 -->
<settings>
	<!--默认设置懒加载 -->
	<setting name="lazyLoadingEnabled" value="true"/>
</settings>

  • 缓存

一级缓存(默认自动开启)

正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持

1. 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。
3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
一级缓存
package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;

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.Test;

import com.hqyj.dao.BlogDao;


/**
 * 
 * <p>
 * 	一级缓存(mybatis默认开启)
 * 	针对以下效果有效:
 * 	1、session对象一致
 * 	2、session执行的查询条件要一致
 * 	3、session不能执行清空缓存操作、关闭操作
 * 	4、多次查询中不能执行增加、修改、删除操作
 * </p>	
 * @Copyright (C),华清远见
 * @author HC
 * @Date:2018年11月20日
 */
public class First_Cache {
	@Test
	public void testfirstcache() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();
		/**
		 * 	当第一次查询的结果和之后的查询结果是一样的,就不会再去执行多次sql语句,因为第一次查询之后就会把结果放在session的缓存中
		 */
		try {
			BlogDao dao = session.getMapper(BlogDao.class);
			dao.findByid(1);
			dao.findByid(1);
			//session.clearCache();//清理缓存的操作
			//增删改后,缓存需要重新读取
			Blog blog = new Blog();
			blog.setId(1);
			blog.setTitle("sdsadsad");
			blog.setContent("11111111111");
			dao.update(blog);
			session.commit();
			
		}finally {
			session.close();
		}
	}
}

日志结果
2018-11-20 19:55:40,658 [main] DEBUG [com.hqyj.dao.BlogDao] - Cache Hit Ratio [com.hqyj.dao.BlogDao]: 0.0
2018-11-20 19:55:40,853 [main] DEBUG [com.hqyj.dao.BlogDao.findByid] - ==>  Preparing: select * from blog where id = ?  
//虽然查询了两次,但还是只调用了一次SQL,因为第一次查询已经将结果放在了缓存中
//进行了增删改会自动清除缓存
2018-11-20 19:55:40,878 [main] DEBUG [com.hqyj.dao.BlogDao.findByid] - ==> Parameters: 1(Integer)
2018-11-20 19:55:40,896 [main] DEBUG [com.hqyj.dao.BlogDao.findByid] - <==      Total: 1
2018-11-20 19:55:40,897 [main] DEBUG [com.hqyj.dao.BlogDao] - Cache Hit Ratio [com.hqyj.dao.BlogDao]: 0.0
2018-11-20 19:55:40,897 [main] DEBUG [com.hqyj.dao.BlogDao.update] - ==>  Preparing: update blog set title=?,content=? where id=? 
2018-11-20 19:55:40,898 [main] DEBUG [com.hqyj.dao.BlogDao.update] - ==> Parameters: sdsadsad(String), 11111111111(String), 1(Integer)
2018-11-20 19:55:40,900 [main] DEBUG [com.hqyj.dao.BlogDao.update] - <==    Updates: 1
二级缓存

全局文件

<!--系统设置 -->
<settings>
	<!-- 设置二级缓存 -->
	<setting name="cacheEnabled" value="true"/>
</settings>

Mapper文件

<mapper namespace="com.hqyj.dao.BlogDao">

<!--   二级缓存
 	mapper文件中需要添加<cache 
			eviction="LRU"  //回收策略为最近最少使用策略
			flushInterval="60000" //自动刷新时间60s
			size="512" //最多缓存512个引用对象
			readOnly="true"/> //只读
			> -->
 <cache></cache>

二级缓存测试类

package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;

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.Test;

import com.hqyj.dao.BlogDao;


/**
 * 二级缓存
 * 1、二级缓存绑定在<mapper namespace="com.hqyj.dao.BlogDao">而非session对象
 * 2、使用二级缓存要做一下操作:
 * 		全局配置文件中,<setting name="cacheEnabled" value="true"/>
 * 		查询具体的实体类需要实现序列化接口
 * 		mapper文件中需要添加<cache 
			eviction="LRU"  //回收策略为最近最少使用策略
			flushInterval="60000" //自动刷新时间60s
			size="512" //最多缓存512个引用对象
			readOnly="true"/> //只读
			>
 * @author DELL
 *
 */


public class Second_Cache {
	@Test
	public void testfirstcache() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		//两个session对象
		SqlSession session = sqlSessionFactory.openSession();
		SqlSession session2 = sqlSessionFactory.openSession();

		try {
			BlogDao dao = session.getMapper(BlogDao.class);
			BlogDao dao2 = session2.getMapper(BlogDao.class);
			
			dao.findByid(1);
			//需要提交一次
			session.commit();
			dao2.findByid(1);
			
		}finally {
			session.close();
		}
	}
}
日志:
//命中率
2018-11-20 20:07:45,221 [main] DEBUG [com.hqyj.dao.BlogDao] - Cache Hit Ratio [com.hqyj.dao.BlogDao]: 0.0
2018-11-20 20:07:45,426 [main] DEBUG [com.hqyj.dao.BlogDao.findByid] - ==>  Preparing: select * from blog where id = ? 
//只调用了一次
2018-11-20 20:07:45,452 [main] DEBUG [com.hqyj.dao.BlogDao.findByid] - ==> Parameters: 1(Integer)
2018-11-20 20:07:45,470 [main] DEBUG [com.hqyj.dao.BlogDao.findByid] - <==      Total: 1
2018-11-20 20:07:45,518 [main] DEBUG [com.hqyj.dao.BlogDao] - Cache Hit Ratio [com.hqyj.dao.BlogDao]: 0.5

  • 调用存储过程

BlogDao.java

package com.hqyj.dao;
import java.util.Map;

import com.hqyj.mybatis.Blog;

public interface BlogDao {
	public void findMap(Map<String,Integer> map);
}

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">
  
  <!-- namespace:名称空间 :面向接口编程的时候,必须为接口所在位置 -->
<mapper namespace="com.hqyj.dao.BlogDao">
  
  
    <!-- 调用存储过程
  	<select>中的属性
  		parameterMap:引用<parameterMap>标签的结果
  		statementType:指定Statement的真实类型:CALLABLE 执行调用存储过程的语句
  	<parameterMap>中的属性
		  type:需要传递的参数的真实类型  java.util.Map
		  <parameter>:指定一个参数key-value
		  
	注:使用二级缓存模式的话  需要把缓存设置为false   useCache="false"
		因为不支持带有OUT参数的缓存存储过程
   -->
   
  <select id="findMap" statementType="CALLABLE" useCache="false" parameterMap="getCountMap">
  	call query_id(?,?) <!--该存储过程是计算总人数-->
  
  </select>
  
  <parameterMap type="java.util.Map" id="getCountMap">
  	<parameter property="b_id" mode="IN" jdbcType="INTEGER"/>
  	<parameter property="b_count" mode="OUT" jdbcType="INTEGER"/>
  
  
  </parameterMap>

</mapper>

测试类

package com.hqyj.mybatis;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

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.Test;

import com.hqyj.dao.BlogDao;

/**
 * 
 * <p>
 * 	调用存储过程
 * </p>	
 * @Copyright (C),华清远见
 * @author HC
 * @Date:2018年11月20日
 */
public class CallAbleTest {
	@Test
	public void testfirstcache() throws IOException {
		//装载mybatis配置文件
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session = sqlSessionFactory.openSession();

		try {
			BlogDao dao = session.getMapper(BlogDao.class);
			Map<String,Integer> map = new HashMap<>();
			map.put("b_id", 0);
			dao.findMap(map);
			System.out.println(map.get("b_count"));
			
		}finally {
			session.close();
		}
	}
}

日志:
2018-11-20 20:28:40,125 [main] DEBUG [com.hqyj.dao.BlogDao.findMap] - ==>  Preparing: call query_id(?,?) 
2018-11-20 20:28:40,166 [main] DEBUG [com.hqyj.dao.BlogDao.findMap] - ==> Parameters: 0(Integer)
2

  • 类型处理


类型处理器	              Java 类型	                        JDBC 类型
BooleanTypeHandler	     java.lang.Boolean, boolean	    数据库兼容的 BOOLEAN
ByteTypeHandler	         java.lang.Byte, byte	        数据库兼容的 NUMERIC 或 BYTE
ShortTypeHandler    	 java.lang.Short, short	    	    数据库兼容的 NUMERIC 或 SHORT INTEGER
IntegerTypeHandler	     java.lang.Integer, int	        数据库兼容的 NUMERIC 或 INTEGER
LongTypeHandler	         java.lang.Long, long	        数据库兼容的 NUMERIC 或 LONG INTEGER
FloatTypeHandler	     java.lang.Float, float	      	    数据库兼容的 NUMERIC 或 FLOAT
DoubleTypeHandler	     java.lang.Double, double    	数据库兼容的 NUMERIC 或 DOUBLE
BigDecimalTypeHandler	 java.math.BigDecimal	        数据库兼容的 NUMERIC 或 DECIMAL
StringTypeHandler	     java.lang.String	            CHAR, VARCHAR
ClobReaderTypeHandler	 java.io.Reader	                -
ClobTypeHandler	         java.lang.String             	CLOB, LONGVARCHAR
NStringTypeHandler	     java.lang.String           		NVARCHAR, NCHAR
NClobTypeHandler		     java.lang.String             	NCLOB
BlobInputStreamTypeHandler	java.io.InputStream	        -
ByteArrayTypeHandler	 byte[]	                     	 	 数据库兼容的字节流类型
BlobTypeHandler	byte[]	 BLOB, LONGVARBINARY
DateTypeHandler	         java.util.Date	               TIMESTAMP
DateOnlyTypeHandler	     java.util.Date         	  	 DATE
TimeOnlyTypeHandler	     java.util.Date	               TIME
SqlTimestampTypeHandler	 java.sql.Timestamp	           TIMESTAMP
SqlDateTypeHandler	     java.sql.Date	               DATE
SqlTimeTypeHandler	     java.sql.Time	               TIME
ObjectTypeHandler	     Any	                       OTHER 或未指定类型
EnumTypeHandler	         Enumeration Type	           VARCHAR-任何兼容的字符串类型,存储枚举的名称(而不是索引)
EnumOrdinalTypeHandler	Enumeration Type	           	   任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的索引(而不是名称)。
InstantTypeHandler	     java.time.Instant	           TIMESTAMP
LocalDateTimeTypeHandler	java.time.LocalDateTime		   TIMESTAMP
LocalDateTypeHandler      	java.time.LocalDate    	   DATE
LocalTimeTypeHandler     	java.time.LocalTime	       TIME
OffsetDateTimeTypeHandler	java.time.OffsetDateTime   TIMESTAMP
OffsetTimeTypeHandler	  	  java.time.OffsetTime	   TIME
ZonedDateTimeTypeHandler		java.time.ZonedDateTime	   TIMESTAMP
YearTypeHandler	            java.time.Year	           INTEGER
MonthTypeHandler         	java.time.Month	           INTEGER
YearMonthTypeHandler	    java.time.YearMonth	       	   VARCHAR or LONGVARCHAR
JapaneseDateTypeHandler 	java.time.chrono.JapaneseDate	DATE
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值