(10)Mybatis————JNDI数据源的使用,延迟加载,缓存以及使用注解开发

1,JNDI数据源

2,Mybatis 延迟加载策略

  • 2.1,何为延迟加载?
  • 2.2,使用 assocation 实现延迟加载
  • 2.3,使用 Collection 实现延迟加载

3,Mybatis 缓存

  • 3.1,Mybatis 一级缓存
  • 3.2,Mybatis 二级缓存

4,Mybatis 注解开发

  • 4.1,mybatis 的常用注解说明
  • 4.2,使用 Mybatis 注解实现基本 CRUD
  • 4.3,使用注解实现复杂关系映射开发
  • 4.4,mybatis 基于注解的二级缓存

JNDI数据源

  • JNDI:Java Naming and Directory Interface。是SUN公司推出的一套规范,属于JavaEE技术之一。目的是模仿windows系统中的注册表。

  • JNDI数据源的使用案例:

1,创建Maven的war工程并导入坐标
(10)Mybatis————JNDI数据源的使用,延迟加载,缓存以及使用注解开发_第1张图片
2,项目结构如下:
(10)Mybatis————JNDI数据源的使用,延迟加载,缓存以及使用注解开发_第2张图片

  • 示例代码如下:
  • context.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- 
<Resource 
name="jdbc/test"						        数据源的名称
type="javax.sql.DataSource"						数据源类型
auth="Container"								数据源提供者
maxActive="20"									最大活动数
maxWait="10000"									最大等待时间
maxIdle="5"										最大空闲数
username="root"									用户名
password="root"									密码
driverClassName="com.mysql.jdbc.Driver"			驱动类
url="jdbc:mysql://localhost:3306/test"	        连接url字符串
/>
 -->
<Resource 
name="jdbc/test"
type="javax.sql.DataSource"
auth="Container"
maxActive="20"
maxWait="10000"
maxIdle="5"
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test"
/>
</Context>
  • index.jsp页面
<%@ page import="org.apache.ibatis.io.Resources" %>
<%@ page import="org.apache.ibatis.session.SqlSession" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactory" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactoryBuilder" %>
<%@ page import="zhou.dao.IUserDao" %>
<%@ page import="zhou.entity.User" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.List" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<body>
<h2>Hello World!</h2>
<%
    //1.读取配置文件
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    //2.根据配置文件构建SqlSessionFactory
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(in);
    //3.使用SqlSessionFactory创建SqlSession对象
    SqlSession sqlSession = factory.openSession();
    //4.使用SqlSession构建Dao的代理对象
    IUserDao userDao = sqlSession.getMapper(IUserDao.class);
    //5.执行dao中的findAll方法
    List<User> users = userDao.findAll();
    for(User user : users){
     
        System.out.println(user);
    }
    //6.释放资源
    sqlSession.close();
    in.close();
%>
</body>
</html>
  • pom.xml
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.5</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>JndiDemo</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
      <resources>
        <resource>
          <directory>src/main/java</directory>
          <includes>
            <include>**/*.xml
          
        
      
  

Mybatis 延迟加载策略

1,何为延迟加载?

  • 延迟加载:

    就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载

  • 好处:

    先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快

  • 坏处 :

    因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降

2,使用 assocation 实现延迟加载

  • 修改配置文件,再mybatis-config.xml配置文件中添加:
<!--配置参数-->
<settings>
    <!--开启Mybatis支持延迟加载-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
  • 账户的持久层映射文件:
<!-- 定义封装account和user的resultMap -->
<resultMap id="accountUserMaps" type="account">
    <id property="id" column="id"></id>
    <result property="uid" column="uid"></result>
    <result property="money" column="money"></result>
    <!-- 一对一的关系映射:配置封装user的内容
    select属性指定的内容:查询用户的唯一标识:
    column属性指定的内容:用户根据id查询时,所需要的参数的值
    -->
    <association property="user" column="uid" javaType="user" select="com.zhou.dao.IUserDao.findById"></association>
</resultMap>

<!-- 查询所有 -->
<select id="findAll" resultMap="accountUserMaps">
    select * from account
</select>
  • 用户的持久层映射文件:
<?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.zhou.dao.IUserDao">
<!-- 根据 id 查询 -->
<select id="findById" resultType="user" parameterType="int" >
select * from user where id = #{
     uid}
</select>
</mapper>

3,使用 Collection 实现延迟加载

  • User 实体类:
public class User implements Serializable {
     

	private Integer id;
	private String username;
	private Date birthday;
	private String sex;
	private String address;
}
  • 编写用户和账户持久层接口的方法:
/**
* 查询所有用户,同时获取出每个用户下的所有账户信息
*/
List<User> findAll();

/**
* 根据用户 id 查询账户信息
*/
List<Account> findByUid(Integer uid);
  • 编写用户持久层映射 配置:
<resultMap type="user" id="userMap">
	<id column="id" property="id"></id>
	<result column="username" property="username"/>
	<result column="address" property="address"/>
	<result column="sex" property="sex"/>
	<result column="birthday" property="birthday"/>
	<!-- 
	collection 是用于建立一对多中集合属性的对应关系
	ofType 用于指定集合元素的数据类型
	select 是用于指定查询账户的唯一标识(账户的 dao 全限定类名加上方法名称)
	column 是用于指定使用哪个字段的值作为条件查询
	-->
	<collection property="accounts" ofType="account"
		select="com.zhou.dao.IAccountDao.findByUid" column="id">
	</collection>
</resultMap>
<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
	select * from user
</select>
  • 标签 :主要用于加载关联的集合对象
  • select 属性 :用于指定查询 account 列表的 sql 语句,所以填写的是该 sql 映射的 id
  • column 属性 :用于指定 select 属性的 sql 语句的参数来源,上面的参数来自于 user 的 id 列,所以就写成 id 这一个字段名了

Mybatis 缓存

  • 什么是缓存?

    存在于内存中的临时数据

  • 为什么使用缓存?

    减少和数据库的交互次数,提高执行效率

  • 什么情况下使用缓存?

    适用于缓存:

    经常查询且不经常改变的
    数据的正确与否对最终的结果影响不大的

    不适用于缓存:

    经常改变的数据
    数据的正确与否对最终的结果影响很大的(商品库存,银行的汇率)

  • Mybatis 中缓存分为一级缓存,二级缓存

1,Mybatis 一级缓存

  • 它指的是Mybatis中SqlSession对象的缓存,当我们执行查询之后,查询的结果回同时存入到SqlSession为我们提供的一块区域中,该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去SqlSession中查询是否有,有的话直接拿出来用。当SqlSession对象消失时,mybatis的一级缓存也就消失了

  • 一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在

  • 一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存

2,Mybatis 二级缓存

  • 它指的时Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessionFactory对象创建的SqlSession共享其缓存

  • 二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的

  • 二级缓存结构图:
    (10)Mybatis————JNDI数据源的使用,延迟加载,缓存以及使用注解开发_第3张图片

  • 二级缓存的使用步骤

①,第一步:在 mybatis-config.xml 中开启二级缓存

<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>
  • 因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false 代表不开启二级缓存。

②,第二步:配置相关的 Mapper 映射文件

<!-- <cache>标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值。-->
<?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.zhou.dao.IUserDao">
<!-- 开启二级缓存的支持 -->
<cache></cache>
</mapper>

③, 第三步:配置 statement 上面的 useCache 属性

<!-- 根据 id 查询 -->
<select id="findById" resultType="user" parameterType="int" useCache="true">
select * from user where id = #{
     uid}
</select>
  • 将 UserDao.xml 映射文件中的