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

    技术2022-07-10  139

    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 注解实现基本 CRUD4.3,使用注解实现复杂关系映射开发4.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 映射的 idcolumn 属性 :用于指定 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 {}

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

    Processed: 0.015, SQL: 9