Mybatis(三)

目录

延迟加载

一对一实现延迟加载 

 一对多的延时加载

Mybatis缓存

一级缓存

二级缓存

Mybatis注解开发

案例:CRUD实现注解开发

复杂映射

案例:一对一查询

案例:一对多查询

 基于注解设置二级缓存


延迟加载

  • 延迟加载:使用数据时才发起查询,不用的时候不查询,按需查询 ,通常用在一对多、多对多(对多操作)
  • 立即加载:不管用不用,只要一调用方法,马上发起查询,通常用在一对一、多对一(对一操作)

一对一实现延迟加载 

account 与user的关系是一对多

assocation实现延迟加载

  • select:填写我们需要调用的select映射的id
  • column:填写我们需要传递给select映射的参数

核心配置文件:配置延时加载

    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

user表:

public interface Iuser {
    user findById(int id);
}
<?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.dome2.dao.Iuser">

    <select id="findById" resultType="user" parameterType="int">
        select * from user where id=#{id}
    </select>

</mapper>

account表:

public interface Iaccount {

    List<account>findAll_t3();
}
<?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">

    <resultMap id="account_1" type="account">
        <id property="ID" column="ID"/>
        <result property="UID" column="UID"/>
        <result property="MONEY" column="MONEY"/>
<!--        可以理解为将uid的参数传入Iuser的findById中 -->
        <association property="user" javaType="user" select="com.dome2.dao.Iuser.findById" column="uid"/>
    </resultMap>
    <select id="findAll_t3" resultMap="account_1">
        select * from account
    </select>

</mapper>

运行结果:

获取查询的结果集 并且遍历  

因为需要对user进行查询,所以查询到uid后,会对user进行查询(延时加载)

获取查询的结果集 不遍历(不需要对user进行查询)

 如果不对user进行查询等操作,则不会对其加载

 一对多的延时加载

user对account是一对多

使用collection实现延时加载

select、colum属性与assocation的属性一样

account表:
 

public interface Iaccount {
   
    List<account>findById(int id);
}
<?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.dome2.dao.Iaccount">


    <select id="findById" parameterType="int" resultType="account">
        select * from account where uid=#{id}
    </select>

</mapper>

user表:

public interface Iuser {
   
    List<user> findAll_1();

}
<?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.dome2.dao.Iuser">

    <resultMap id="rm" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="address" column="address"/>
        <result property="sex" column="sex"/>
        <result property="birthday" column="birthday"/>
        <collection property="list" ofType="account" select="com.dome2.dao.Iaccount.findById" column="id"/>
    </resultMap>
    <select id="findAll_1" resultMap="rm">
        select * from user
    </select>

</mapper>

运行结果

获取结果集 并且遍历

通过获取的id进行account的查询

获取结果集 不遍历(不需要对account进行加载)

Mybatis缓存

原理图

一级缓存存储的是对象;二级缓存存储的是数据 

一级缓存

该缓存是sqlseesion的范围的缓存,当调用SqlSession的修改、添加、删除,commit()、close()等方法时,就会清空缓存。

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

示例代码

使用同一个SqlSession对象时,第一次查询会将查询结果存入缓存中,第二次查询直接从缓存中取

 user byId = iuser.findById(44);
 user byId1 = iuser.findById(44);
 System.out.println(byId==byId1);//true

清空SqlSession缓存后的运行结果

user byId = iuser.findById(41);
//        清空缓存
        sqlSession.clearCache();
//        重新获取代理对象
iuser = sqlSession.getMapper(Iuser.class);
user byId1 = iuser.findById(41);
System.out.println(byId==byId1);//false

二级缓存

SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。

步骤

  • 让Mybatis框架支持二级缓存(在SqlMapnConfig.xml中配置)
  • 让当前的映射文件支持二级缓存(映射文件)
  • 让当前的操作支持二级缓存(在select标签中配置)

示例代码

主配置文件

<settings>
        <setting name="cacheEnabled" value="true"/>
</settings>

user的映射文件

<?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.dome2.dao.Iuser">
<!--    开启二级缓存-->
    <cache/>

<!--    userCache 开启二级缓存-->
    <select id="findById" resultType="user" parameterType="int" useCache="true">
        select * from user where id=#{id}
    </select>

    <resultMap id="rm" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="address" column="address"/>
        <result property="sex" column="sex"/>
        <result property="birthday" column="birthday"/>
        <collection property="list" ofType="account" select="com.dome2.dao.Iaccount.findById" column="id"/>
    </resultMap>
    <select id="findAll_1" resultMap="rm">
        select * from user
    </select>

</mapper>

测试代码:
 

        SqlSession sqlSession = factory.openSession();
        Iuser mapper = sqlSession.getMapper(Iuser.class);
        user byId = mapper.findById(41);
        System.out.println(byId);
//        一级缓存消失
        sqlSession.close();
        SqlSession sqlSession1 = factory.openSession();
        Iuser mapper1 = sqlSession1.getMapper(Iuser.class);
        user byId1 = mapper1.findById(41);
        System.out.println(byId1);
        sqlSession1.close();
        System.out.println(byId==byId1);

同一个SqlFactory 下不同的SqlSession

运行结果

 从图片可以看出,只执行了一次sql语句,输出false的原因,二级缓存存储的是数据不是对象

Mybatis注解开发

作用:省去了编写接口映射文件的时间

注解名称含义
@Select进行查询
@Insert进行增加
@Delete进行删除
@Update进行修改
@Results可以进行复杂关系映射 内部可以使用多个@Result
@Result可以进行详细的关系映射
@One替代了assocation标签,可以进行一对一查询
@Many替代了collestion标签,可以进行一对多查询

@Result的属性

  • id:是否为主键
  • column:数据库的表名
  • property:类的成员属性
  • one:需要使用@One注解
  • many:需要使用@Many注解

案例:CRUD实现注解开发

接口:

public interface Iuser {
//    增加
    @Insert("insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})")
    void insert(user u);
//    删
    @Delete("delete from user where id=#{id}")
    void delete(int id);
    @Update("update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}where id=#{id}")
//    改
    void update(user u);
//    查
//    所有
    @Select("select * from user")
    List<user> FindAll();
//    根据id查询
    @Select("select * from user where id=#{id}")
    user FindById(int id);
//    根据name模糊查询
    @Select("select * from user where username like #{name}")
   List<user> FindByName(String name);
//    查询聚合函数
    @Select("select count(id) from user")
    int count();
}

在核心配置文件中导入接口

 <mappers>
<!--        导入该接口-->
<!--        <mapper class="com.dao.Iuser"/>-->
<!--        注册包内所有接口-->
        <package name="com.dao"/>
    </mappers>

复杂映射

当实体类的属性名和数据库的列名不一致时,需要复杂映射

实体类:

@Setter @Getter @ToString
public class AUser {
    private int Aid;
    private String Ausername;
    private Date Abirthday;
    private String Asex;
    private String Aaddress;
}

接口:

 @Insert("insert into user(username,birthday,sex,address) values(#{Ausername},#{Abirthday},#{Asex},#{Aaddress})")
    @Results(id = "userMap",value = {
            @Result(id = true, column = "id",property ="Aid" ),
            @Result(column = "username",property = "Ausername"),
            @Result(column = "birthday",property = "Abirthday"),
            @Result(column = "sex",property = "Asex"),
            @Result(column = "address",property = "Aaddress")
    })
    void insert(AUser u);

案例:一对一查询

account表与user表的关系是一对一

account表:

@Setter @Getter @ToString
public class account {
    private int ID;
    private int UID;
    private double MONEY;
//    account 对 user 是1对1
    private  user user;
}

接口:

public interface Iaccount {
    @Select("select * from account")
    @Results({
            @Result(id = true,column = "ID",property ="ID" ),
            @Result(column = "MONEY",property = "MONEY"),
            @Result(column = "UID",property = "UID"),
            @Result(column = "UID" ,property = "user",
            one = @One(select = "com.dao.Iuser.FindById",fetchType = FetchType.LAZY))
//            FetchType.LAZY:延时加载
    })
    List<account> findAll();
}

@One注解:将UID参数传入Iuser接口的FindById方法中进行查询,并且返回结果

案例:一对多查询

user与account的关系是一对多

user表:

@Setter @Getter @ToString
public class user {
    private int id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
//    user 与account 的关系是一对多
    private List<account> list;
}

接口:

public interface Iuser {

    @Select("select * from user")
    @Results(
            {
                    @Result(id = true,column = "id",property = "id"),
                    @Result(column = "username",property = "username"),
                    @Result(column = "birthday",property = "birthday"),
                    @Result(column = "sex",property = "sex"),
                    @Result(column = "address",property = "address"),
                    @Result(column = "id",property = "list", many = @Many(select = "com.dao.Iaccount.findByID",fetchType = FetchType.LAZY)
                    )
            }
    )
    List<user> FindAll_t1();
}

@Many注解:将id参数传入Iaccount的findByID方法 ,并且将结果传回

 基于注解设置二级缓存

步骤:

  • 在核心文件中开启二级缓存支持
  • 在持久层接口中配置二级缓存

示例代码:

核心配置文件添加代码:

<settings>
        <setting name="cacheEnabled" value="true"/>
 </settings>

持久层接口配置二级缓存

@CacheNamespace(blocking = true)
public interface Iaccount {...}

运行结果

 从图中可以看出,sql代码只执行了一次

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值