美文网首页
08- MyBatis进阶

08- MyBatis进阶

作者: XAbo | 来源:发表于2021-02-14 11:07 被阅读0次

    一、MyBatis的延迟加载

    • 一对多,多对多:通常情况下我们都是采用延迟加载。
    • 多对一,一对一:通常情况下我们都是采用立即加载。

    开启延迟加载mybatis-config.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>
    
       <!--配置参数-->
        <settings>
            <!--开启Mybatis支持延迟加载-->
            <setting name="lazyLoadingEnabled" value="true"/>
           <!--开启时,任何方法的调用都会加载该对象的所有属性,否则按需加载。-->
            <setting name="aggressiveLazyLoading" value="false"></setting>
        </settings>
      
        <!--使用typeAliases配置别名,只能配置domain中类的别名-->
       <typeAliases>
           <package name="com.example.domain"></package>
       </typeAliases>
       <properties resource="jdbc.properties"></properties>
        <!--配置环境-->
        <environments default="development">
            <environment id="development">
                <!-- 配置事务类型 -->
                <transactionManager type="JDBC"></transactionManager>
                <!-- 配置数据源(连接池) -->
                <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>
            <package name="com.example.dao"></package>
        </mappers>
    </configuration>
    

    1.1 一对一

    没有延迟加载:AccountMapper.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">
    <mapper namespace="com.example.dao.AccountDao">
    
      <resultMap id ="accountUserMap" type ="account">
         <id property="id" column="aid"></id>
         <result property="uid" column="uid"></result>
         <result property="money" column="money"></result>
        <!--配置一对一-->
         <association property="user" column="uid"  javaype="com.example.domain.User">
             <id property="id" column="id"></id>
             <result property="username" column="username"></result>
             <result property="address" column="address"></result>
             <result property="sex" column="sex"></result>
             <result property="birthday" column="birthday"></result>
         </association>
       </resultMap>
    
        <select id="findAll" resultMap="accountUserMap">
         select u.*,a.id as aid ,a.uid ,a.money from  [Account] a ,[User] u where u.id = a.uid    
       </select>
    </mapper>
    

    使用延迟加载:AccountMapper.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">
    <mapper namespace="com.example.dao.AccountDao">
    
        <resultMap id ="accountUserMap" type ="account">
         <id property="id" column="id"></id>
         <result property="uid" column="uid"></result>
         <result property="money" column="money"></result>
        <!--配置一对一-->
         <association property="user" column="uid" javaType="com.example.domain.User" 
            select="com.example.dao.UserDao.FindById">
        </resultMap>
    
        <select id="findAll" resultMap="accountUserMap">
         select * from  [Account]  
       </select>
    </mapper>
    

    UserMapper.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">
    <mapper namespace="com.example.dao.UserDao">
    
     <resultMap id ="userAccountMap" type ="user">
         <id property="id" column="id"></id>
         <result property="username" column="username"></result>
         <result property="address" column="address"></result>
         <result property="sex" column="sex"></result>
         <result property="birthday" column="birthday"></result>
        <!--配置一对多-->
         <collection  property="accounts"  ofType="com.example.domain.Account">
             <id property="aid" column="aid"></id>  
             <result property="uid" column="uid"></result>
             <result property="money" column="money"></result>
          </collection>
       </resultMap>
    
        <select id="findAll" resultMap="userAccountMap">
            select * from  [User] u left  join Accout a on u.id = a.uid
        </select>
       <select id="findById"  parameterType= "INT" resultType="user">
            select * from  [User]  where id = ${id}
        </select>
    </mapper>
    

    1.2 一对多

    使用延迟加载:UserMapper.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">
    <mapper namespace="com.example.dao.UserDao">
    
     <resultMap id ="userAccountMap" type ="user">
         <id property="id" column="id"></id>
         <result property="username" column="username"></result>
         <result property="address" column="address"></result>
         <result property="sex" column="sex"></result>
         <result property="birthday" column="birthday"></result>
        <!--配置一对多-->
         <collection  property="accounts"  ofType="com.example.domain.Account"
            select="com.example.dao.Account.findAccountByUid" column="id">
         </collection>
       </resultMap>
    
        <select id="findAll" resultMap="userAccountMap">
            select * from  [User]  
        </select>
       <select id="findById"  parameterType= "INT" resultType="user">
            select * from  [User]  where id = ${id}
        </select>
    </mapper>
    

    AccountMapper.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">
    <mapper namespace="com.example.dao.AccountDao">
    
        <resultMap id ="accountUserMap" type ="account">
         <id property="id" column="id"></id>
         <result property="uid" column="uid"></result>
         <result property="money" column="money"></result>
        <!--配置一对一-->
         <association property="user" column="uid" javaType="com.example.domain.User" 
            select="com.example.dao.UserDao.FindById">
        </resultMap>
    
        <select id="findAll" resultMap="accountUserMap">
         select * from  [Account]  
        </select>
      
        <select id="findAccountByUid" resultType="account">
         select * from  [Account]  where uid=#{uid} 
        </select>
    </mapper>
    

    二、MyBatis的缓存

    2.1 一级缓存

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

    调用SqlSession的修改、添加、删除、提交和关闭等方法时候,一级缓存就会被清空。

    @Test
    public void testFirstLevelCache() {
        User u1 = userDao.findById(1);
        User u2 = userDao.findById(1); 
        System.out.println(u1==u2);
    }
    

    结果:true。

    2.2 二级缓存

    二级缓存:它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。

    二级缓存
    • 第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
       <settings>
           <setting name="cacheEnabled" value="true"/>
       </settings>
    
    • 第二步:让当前的映射文件支持二级缓存(在UserDao.xml中配置)
    • 第三步:让当前的操作支持二级缓存(在select标签中配置)
    <mapper namespace="com.example.dao.UserDao">
       <cache/>
       <select id="findById"  parameterType= "INT" resultType="user" useCache="true">
            select * from  [User]  where id = ${id}
        </select>
    </mapper>
    

    客户端:

    @Test
    public void testSecondLevelCache() {
       SqlSession sqlSession1 = factory.openSession(); 
       UserDao dao1 = sqlSession1.gerMapper(UserDao.class);
       User u1 = dao1 .findById(1);
       sqlSession1.close(); // 一级缓存关闭
    
       SqlSession sqlSession2 = factory.openSession(); 
       UserDao dao2 = sqlSession2.gerMapper(UserDao.class);
       User u2 = dao2 .findById(1); 
       sqlSession2.close(); // 一级缓存关闭
    
       System.out.println(u1==u2);    // false
    }
    
    sql仅执行一次

    三、MyBatis注解(了解)

    MyBatis的主配置文件不变,仅修改mapper.xml。

    @Insert:实现新增 
    @Update:实现更新 
    @Delete:实现删除 
    @Select:实现查询 
    @Result:实现结果集封装 
    @Results:可以与@Result 一起使用,封装多个结果集 
    @ResultMap:实现引用@Results 定义的封装 
    @One:实现一对一结果集封装 
    @Many:实现一对多结果集封装 
    @SelectProvider: 实现动态SQL映射 
    @CacheNamespace:实现注解二级缓存的使用 
    

    3.1 基础应用

    UserDao:

    public interface UserDao {
    
        @Select("select * from user")
        List<User> findAll();
    
        @Insert("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
        void saveUser(User user);
    
        @Update("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}")
        void updateUser(User user);
    
        @Delete("delete from user where id=#{id} ")
        void deleteUser(Integer userId);
    
        @Select("select * from user  where id=#{id} ")
        User findById(Integer userId);
    
        //  @Select("select * from user where username like #{username} ")
        @Select("select * from user where username like '%${value}%' ")
        List<User> findUserByName(String username);
    
        @Select("select count(*) from user ")
        int findTotalUser();
    }
    

    3.2 复杂应用

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

    @Results 注解代替的是标签<resultMap> ;该注解中可以使用单个@Result 注解,
    也可以使用@Result集合 @Results({@Result(),@Result()})或@Results(@Result()) 
     
    @Result 注解代替了<id>标签和<result>标签  
    @Result 中属性介绍: id是否是主键字段;column 数据库的列名;property需要装配的属性名  
    
    one  需要使用的@One 注解(@Result(one=@One)()))  
    many  需要使用的@Many 注解(@Result(many=@many)())) 
    
    @One 注解(一对一) 代替了<assocation>标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。 
    @One 注解属性介绍:  
    select指定用来多表查询的sqlmapper fetchType会覆盖全局的配置参数 lazyLoadingEnabled。 
    使用格式: @Result(column=" ",property="",one=@One(select="")) 
     
    @Many 注解(多对一)代替了<Collection>标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。  
    注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,
    属性的 javaType (一般为 ArrayList)但是注解中可以不定义;  
    使用格式:  @Result(property="",column="",many=@Many(select="")) 
    

    3.2.1 一对一

    AccountDao:

    public interface AccountDao {
        @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(property = "user",column = "uid",one=@One(select="com.itheima.dao.IUserDao.findById",fetchType= FetchType.EAGER))
        })
        List<Account> findAll();
        @Select("select * from account where uid = #{userId}")
        List<Account> findAccountByUid(Integer userId);
    }
    

    UserDao:

    @CacheNamespace(blocking = true)
    public interface UserDao {
        @Select("select * from user")
        @Results(id="userMap",value={
                @Result(id=true,column = "id",property = "userId"),
                @Result(column = "username",property = "userName"),
                @Result(column = "address",property = "userAddress"),
                @Result(column = "sex",property = "userSex"),
                @Result(column = "birthday",property = "userBirthday"),
                @Result(property = "accounts",column = "id",
                        many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid",
                                    fetchType = FetchType.LAZY))
        })
        List<User> findAll();
        @Select("select * from user  where id=#{id} ")
        @ResultMap("userMap")
        User findById(Integer userId);
        @Select("select * from user where username like #{username} ")
        @ResultMap("userMap")
        List<User> findUserByName(String username);
    }
    

    3.2.2 一对多

    UserDao:

    @CacheNamespace(blocking = true)
    public interface UserDao {
        @Select("select * from user")
        @Results(id="userMap",value={
                @Result(id=true,column = "id",property = "userId"),
                @Result(column = "username",property = "userName"),
                @Result(column = "address",property = "userAddress"),
                @Result(column = "sex",property = "userSex"),
                @Result(column = "birthday",property = "userBirthday"),
                @Result(property = "accounts",column = "id",
                        many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid",
                                    fetchType = FetchType.LAZY))
        })
        List<User> findAll();
        @Select("select * from user  where id=#{id} ")
        @ResultMap("userMap")
        User findById(Integer userId);
        @Select("select * from user where username like #{username} ")
        @ResultMap("userMap")
        List<User> findUserByName(String username);
    }
    

    相关文章

      网友评论

          本文标题:08- MyBatis进阶

          本文链接:https://www.haomeiwen.com/subject/vlcyxltx.html