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

1,JNDI数据源

2,Mybatis 延迟加载策略

3,Mybatis 缓存

4,Mybatis 注解开发

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

  • JNDI数据源的使用案例:

1,创建Maven的war工程并导入坐标
在这里插入图片描述
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</include>
          </includes>
        </resource>
      </resources>
  </build>
</project>
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 的

  • 二级缓存结构图:
    在这里插入图片描述

  • 二级缓存的使用步骤

①,第一步:在 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 映射文件中的<select>标签中设置 useCache="true"代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。

  • 注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化方式来保存对象。

Mybatis 注解开发

1,mybatis 的常用注解说明

@Insert:实现新增

@Update:实现更新

@Delete:实现删除

@Select:实现查询

@Result:实现结果集封装

@Results:可以与@Result 一起使用,封装多个结果集

@ResultMap:实现引用@Results 定义的封装

@One:实现一对一结果集封装

@Many:实现一对多结果集封装

@SelectProvider: 实现动态 SQL 映射

@CacheNamespace:实现注解二级缓存的使用

2,使用 Mybatis 注解实现基本 CRUD

  • 查询操作:
@Select("select * from user")
@Results(id="userMap",
        value= {
                @Result(id=true,column="id",property="id"),
                @Result(column="username",property="username"),
                @Result(column="sex",property="sex"),
                @Result(column="address",property="address"),
                @Result(column="birthday",property="birthday")
        })
List<User> findAll();


/**
* 根据 id 查询一个用户
*/
@Select("select * from user where id = #{uid} ")
@ResultMap("userMap")
User queryUserById(Integer userId);

/**
 * 查询使用聚合函数
*/
@Select("select count(*) from user ")
int findTotal();

/**
* 模糊查询
*/
@Select("select * from user where username like #{username} ")
List<User> findByName(String name);
  • 保存操作:
/**
 * 保存操作
 */
@Insert("insert into user(username,sex,birthday,address)values(#{username},#{sex},#{birthday},#{address})")
@SelectKey(keyColumn="id",keyProperty="id",resultType=Integer.class,before = false, statement = { "select last_insert_id()" })
int saveUser(User user);
  • 更新操作:
/**
 * 更新操作
 */
@Update("update  user  set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday}  where  id =#{id} ")
int updateUser(User user);
  • 删除操作:
/**
 * 删除用户
 */
@Delete("delete from user where id = #{uid} ")
int deleteUser(Integer userId);

3,使用注解实现复杂关系映射开发

  • 实现复杂关系映射之前我们可以在映射文件中通过配置来实现,在使用注解开发时我们需要借助@Results 注解,@Result 注解,@One 注解,@Many 注解。

  • 复杂关系映射的注解说明:

    • @Results 注解代替的是标签<resultMap>该注解中可以使用单个@Result 注解,也可以使用@Result 集合@Results({@Result(),@Result()})或@Results(@Result())

    • @Resutl 注解代替了 <id> 标签和<result> 标签

    • @Result 中 属性介绍:

      id 是否是主键字段

      column 数据库的列名

      property 需要装配的属性名

    • one 需要使用的@One 注解(@Result(one=@One)()))

    • many 需要使用的@Many 注解(@Result(many=@many)()))

    • @One 注解(一对一),代替了<assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。

    • @One 注解属性介绍:

      select 指定用的 来多表查询的 sqlmapper

      fetchType 会覆盖全局的配置参数 lazyLoadingEnabled,LAZY(延迟加载), EAGER(立即加载)

    • 使用格式:@Result(column=" ",property="",one=@One(select=""))

    • @Many 注解(多对一),代替了<Collection> 标签, 是多表查询的关键,在注解中用来指定子查询返回对象集合。

    • 注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType(一般为 ArrayList)但是注解中可以不定义;

    • 使用格式:@Result(property="",column="",many=@Many(select=""))

  • 使用 注解 实现一对一 复杂关系映射 及延迟加载的示例代码:

/**
 * 查询所有账户,采用延迟加载的方式查询账户的所属用户
 */
@Select("select * from account")
@Results(id="accountMap",
        value= {
                @Result(id=true,column="id",property="id"),
                @Result(column="uid",property="uid"),
                @Result(column="money",property="money"),
                @Result(column="uid",
                        property="user",
                        one=@One(select="com.zhou.dao.IUserDao.findById",
                                fetchType= FetchType.LAZY)
                )
        })
List<Account> findAll();

@Select("select * from user where id = #{uid} ")
@ResultMap("userMap")
User findById(Integer userId);
  • 使用 注解 实现一对多复杂关系映射示例代码:
/**
 * 查询所有用户
 */
@Select("select * from user")
@Results(id="userMap",
        value= {
                @Result(id=true,column="id",property="id"),
                @Result(column="username",property="username"),
                @Result(column="sex",property="sex"),
                @Result(column="address",property="address"),
                @Result(column="birthday",property="birthday"),
                @Result(column="id",property="accounts",
                        many=@Many(
                                select="com.zhou.dao.AccountDao.findByUid",
                                fetchType= FetchType.LAZY
                        )
                )
        })
List<User> findAll();

@Select("select * from account where uid = #{uid} ")
List<Account> findByUid(Integer userId);

4,mybatis 基于注解的二级缓存

  • 在 mybatis-config.xml 中开启二级缓存支持:
<!-- 配置二级缓存 -->
<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>
  • 在持久层接口中使用注解配置二级缓存:
@CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存
public interface IUserDao {}

下一章, MyBatisPlus————条件构造器,AR,代码生成器以及插件扩展

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值