08- MyBatis进阶

2021-02-14  本文已影响0人  XAbo

一、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共享其缓存。

二级缓存
   <settings>
       <setting name="cacheEnabled" value="true"/>
   </settings>
<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);
}
上一篇下一篇

猜你喜欢

热点阅读