-
延迟加载
-
在真正使用数据时才发起查询,不用的时候不查询(懒加载)
-
-
立即加载
-
不管用不用,只要一调用,就立即发起查询,就跟平常一样调用查询即可
-
-
数据库表格之间的关系
-
一对多、多对多:尽量使用延迟加载
-
多对一、一对一:尽量使用立即加载
-
-
懒加载的实现方式
-
以words与groups为实例实现一对一的懒加载,之前的配置文件信息可以不用太多的修改。
-
words的指定映射配置文件
<?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.dao.WordsDao"> <!-- 配置 查询结果的列名和实体类的属性名的对应关系 --> <resultMap id="wordsMap" type="com.domain.Words"> <!-- 主键的对应字段 --> <id property="id" column="id"></id> <!-- 非主键的对应字段 --> <result property="word" column="word"></result> <result property="translation" column="translation"></result> <result property="introduction" column="introduction"></result> <result property="group_id" column="group_id"></result> <result property="add_time" column="add_time"></result> <result property="star" column="star"></result> </resultMap> <!-- 定义封装Words和Groups的resultMap --> <resultMap id="wordsGroupsMap" type="com.domain.Words"> <!-- 前面的名称对应的是实体类的成员变量,后面的名称对应的是sql结果集或者表格的列名称 --> <!-- 主键的对应字段 --> <id property="id" column="id"></id> <!-- 非主键的对应字段 --> <result property="word" column="word"></result> <result property="translation" column="translation"></result> <result property="introduction" column="introduction"></result> <result property="group_id" column="group_id"></result> <result property="add_time" column="add_time"></result> <result property="star" column="star"></result> <!-- 一对一的懒加载方式 select属性指定的内容是查询“词组”的唯一标识 column属性指定的内容是“词组”根据id查询时所需要的参数的值 --> <association property="groups" column="gid" javaType="com.domain.Groups" select="com.dao.WordsDap.findGroupsById"></association> </resultMap> <!-- 配置查询所有 --> <select id="findAll" resultType="com.domain.Words"> select * from words; </select> </mapper>
-
groups的指定映射配置文件
<?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.dao.GroupsDao"> <!-- 配置 查询结果的列名和实体类的属性名的对应关系 --> <resultMap id="groupsMap" type="com.domain.Groups"> <!-- 主键的对应字段 --> <id property="id" column="id"></id> <!-- 非主键的对应字段 --> <result property="name" column="name"></result> <result property="add_time" column="add_time"></result> </resultMap> <!-- 定义Groups的resultMap --> <resultMap id="groupsWordsMap" type="com.domain.Groups"> <id property="id" column="gid"></id> <result property="name" column="gname"></result> <result property="add_time" column="gadd_time"></result> <!-- 配置groups对象中words集合的映射 --> <collection property="words" ofType="com.domain.Words"> <id property="id" column="id"></id> <result property="word" column="word"></result> <result property="translation" column="translation"></result> <result property="introduction" column="introduction"></result> <result property="group_id" column="group_id"></result> <result property="add_time" column="add_time"></result> <result property="star" column="star"></result> </collection> </resultMap> <!-- 配置查询所有 --> <select id="findAll" resultMap="groupsMap"> select * from groups; </select> <!-- 根据id查询信息 --> <select id="findGroupsById" parameterType="int" resultType="com.domain.Groups"> select * from groups where id = #{wid}; </select> </mapper>
-
在SqlMapConfig.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"> <!-- mybatis的主配置文件 --> <configuration> <properties resource="jdbcConfig.properties"></properties> <!-- 懒加载的配置方式 --> <settings> <!-- mybatis的懒加载 --> <setting name="lazyLoadingEnabled" value="true"></setting> <setting name="aggressiveLazyLoading" value="false"></setting> </settings> <!-- 配置环境 --> <environments default="mysql"> <!-- 配置MySQL的环境 --> <environment id="mysql"> <!-- 配置事务类型 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源(连接池) --> <dataSource type="POOLED"> <!-- 配置连接数据库的4个基本信息 --> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/dao/WordsDao.xml" /> <mapper resource="com/dao/GroupsDao.xml" /> </mappers> </configuration>
-
-
2、mybatis的缓存
-
缓存
-
存在于内存中的临时数据
-
-
缓存优点
-
减少与数据库的交互次数,提高执行效率
-
-
缓存使用与否
-
经常查询并且数据不易改变,数据的正确与否对结果影响不大
-
经常改变数据,数据的正确与否对结果影响很大
-
-
一级缓存
-
mybatis中SqlSession对象的缓存
-
当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供的一块区域中。该区域的结构是一个map,当我们再次查询相同的数据时,mybatis会优先查看SqlSession中是否含有查询的数据,有则用。当SqlSession对象销毁时,一级缓存区域也就消失了。
-
实现方式就是之前的使用的SqlSession,清空缓存的方法:sqlSession.clearCache()
-
-
二级缓存
-
mybatis中SqlSessionFactory对象的缓存
-
由同一个SqlSessionFactory对象创建的SqlSession共享其缓存
-
二级缓存的使用步骤
-
让mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
<settings> <setting name="cacheEnabled" value="true"></setting> </settings>
-
让当前指定的映射配置文件支持二级缓存
<cache />
-
让当前的数据库操作支持二级缓存(在select标签配置)
<select ... useCache="true"> ... </select>
-
-
3、mybatis的注解开发
-
基于CURD的四种注解:@Select、@Insert、@Update、@Delete。
-
使用时需要导入import org.apache.ibatis.annoatioins.Select;然后在dao层上的接口类的抽象方法上添加注解,使用如下:
import org.apache.ibatis.annoatioins.Select; import com.mypro.domain.User; public interface UserDao{ @Select("select * from user") List<User> findAll(); }
这样写的好处就是代替了指定映射配置文件的某种数据库的操作编写,以前的操作均可以不用变,而且实体类的成员变量和数据库表格的字段名是一样的(前提),但是指定映射配置文件的位置不能留在原地或者删除。注解里面的语句和在映射配置文件的语句也是一样的
-
为解决上述实体类的成员变量和数据库表格的字段名可能不一样的问题,mybatis提供了别名的注解方式:@Results 可以赋值一个id值,之后的相同操作可以直接使用@ResultMap("id名称") / @ResultMap(value="id名称") / @ResultMap(value={"id名称"})
import org.apache.ibatis.annoations.Select; import com.mypro.domain.User; public interface UserDao{ @Select("select * from user") @Results(id="userMap", value={ @Result(id=true, column="表格主键", property="成员变量"), @Result(column="表格字段名", property="成员变量") }) List<User> findAll(); @Select("select * from user where id=#{id}") @ResultMap("userMap") User findOneById(Integer id); }
-
上述两种操作是单表操作,现以用户信息和账号信息为例(一对多),查询当前中账号信息及其所属的用户信息。
-
显然账号信息实体类中有用户信息类的对象的引用
-
在账户信息dao层接口抽象方法@Results注解封装方式如下(Result中one=@One表示一对一操作,many=@Many表示一对多操作;FetchType中EAGER表示立即加载,LAZY表示延迟加载;select指定的是UserDao里面的抽象方法)
import org.apache.ibatis.annoations.Select; import com.mypro.domain.Account; import com.mypro.domain.User; public interface AccountDao{ @Select("select * from account") @Results(id="accountMap", value={ @Result(id=true, column="表格主键", property="成员变量"), @Result(column="表格字段名", property="成员变量"), @Result(column="uid", property="user", one=@One( select="com.mypro.dao.UserDao.findOneById", fetchType=FetchType.EAGER)) }) List<User> findAll(); @Select("select * from account where uid=#{uid}") @ResultMap("accountMap") List<User> findAllById(Integer id); }
-
-
用户信息和账户信息为例(一对多),查询当前用户信息及其所有的账户信息。
-
显然用户信息实体类中有账户信息类的对象的引用集合
-
在用户信息dao层接口抽象方法@Results注解封装方式如下(Result中one=@One表示一对一操作,many=@Many表示一对多操作;FetchType中EAGER表示立即加载,LAZY表示延迟加载;select指定的是AccountDao里面的抽象方法)
import org.apache.ibatis.annoations.Select; import com.mypro.domain.User; public interface UserDao{ @Select("select * from user") @Results(id="userMap", value={ @Result(id=true, column="表格主键", property="成员变量"), @Result(column="表格字段名", property="成员变量"), @Result(column="id", property="accounts", many=@Many( select="com.mypro.dao.AccountDao.findAllById", fetchType=FetchType.LAZY)) }) List<User> findAll(); @Select("select * from user where id=#{id}") @ResultMap("userMap") User findOneById(Integer id); }
-
-
-
注解开发配置二级缓存
-
一级缓存和以前一样,二级缓存只需要两步
-
第一步可以参考之前的二级缓存的第一步配置
-
import org.apache.ibatis.annoations.Select; import com.mypro.domain.User; @CacheNamespace(blocking=true) public interface UserDao{ @Select("select * from user") @Results(id="userMap", value={ @Result(id=true, column="表格主键", property="成员变量"), @Result(column="表格字段名", property="成员变量"), @Result(column="id", property="accounts", many=@Many( select="com.mypro.dao.AccountDao.findAllById", fetchType=FetchType.LAZY)) }) List<User> findAll(); @Select("select * from user where id=#{id}") @ResultMap("userMap") User findOneById(Integer id); }
-
-