Mybatis的多表联查写法和数据懒加载、缓存

如何确定表关系:
    依靠外键
如何在实体中描述表关系:
    建立对方的引用。
    如果是一的一方,它关联的就是对方的集合(建立集合引用)
    如果是多的一方,它关联的就是对方的对象(建立对象引用)
Mybatis中配置关联查询: 以用户和订单为例

 <collection>标签

 常用属性:
         property:指定集合的名称
         javaType:指定集合的类型
         ofType:指定集合元素的类型

--查询一个用户时携带其所有订单内容

//一对多 条件查询
User findOneByMore(Integer uid);
<!--一对多 条件查询-->
<resultMap id="findOneByMoreMap" type="User">
    <id column="uid" property="uid"></id>
    <result column="name" property="name"></result>
    <result column="password" property="password"></result>
    <result column="email" property="email"></result>
    <result column="birthday" property="birthday"></result>
    <collection property="userAccount" javaType="java.util.List" ofType="Account">
        <result column="aid" property="aid"></result>
        <result column="accountName" property="accountName"></result>
        <result column="balance" property="balance"></result>
        <result column="uid" property="uid"></result>
    </collection>
</resultMap>
<select id="findOneByMore" resultMap="findOneByMoreMap"> select * from `user` u join account a on a.uid = u.uid where u.uid = #{uid} </select>

--查询所有用户时携带其所有订单内容

//一对多 所有用户
List<User> findAllOneByMore();

同上查询单个的写法,只需更换sql语句

select * from `user` u join account a on a.uid = u.uid

一对一配置对象时:

<association>标签

常用属性:

      property:指定对象的名称
      javaType:指定对象的类型

查询一个订单时想查看用户信息

//一对一
Account findByIdOne(Integer aid);
<!-- 条件查询 一对一 -->
<resultMap id="findByIdOneMap" type="Account">
    <id property="aid" column="aid"></id>
    <result property="accountName" column="accountName"></result>
    <result property="balance" column="balance"></result>
    <result property="uid" column="uid"></result>
    <association property="user" javaType="User">
        <id property="uid" column="uid"></id>
        <result property="name" column="name"></result>
        <result property="password" column="password"></result>
        <result property="email" column="email"></result>
        <result property="birthday" column="birthday"></result>
    </association>
</resultMap>
<select id="findByIdOne" resultMap="findByIdOneMap">
    SELECT * FROM `user` u JOIN account a ON a.uid = u.uid where aid = #{aid}
</select>

复合传值,懒加载用法的配置和举例

我们在查询用户时返回的的是整个订单的Account实体集合和User实体,这样会频繁的创建对象浪费内存空间,使用懒加载机制让其查询时之查询User信息,需要订单Account信息时再查询即可。

反过来思考在查询单条Account订单信息时会携带一条相关的User信息,这样并不会浪费太多内存,可以选择及时加载或懒加载。

配置全局懒加载,主配置文件中

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

同时 association 和 collection 标签上多了一个属性可选 

fetchType = "lazy | eager"
lazy使用懒加载 eager则相反
属性的权重大于全局配置,但是上面所写的一条sql并无法实现懒加载,因为一条语句就查出了所有需要的数据,而我们想要的是分开查询。
这里需要注意的是查询结果呈现出肯定是映射后的实体,假设查询的Account实体,开启懒加载后其中的User属性为空,不查询。
这时调用其 equals, clone, hashCode, toString方法后默认认为要查询User属性并对其进行映射,这可以参考MyBatis中的 Settings属性 lazyLoadTriggerMethods 进行配置

举例

一对一查询
UserMapper.xml中有查询单个User实体的语句
<!--单条件查询-->
<select id="findOneById" resultType="User">
    select * from `user` where uid = #{uid}
</select>

 AccountMapper.xml配置

<!-- 一对一懒加载用法 -->
<resultMap id="findByIdOneOldMap" type="Account">
    <id property="aid" column="aid"></id>
    <result property="accountName" column="accountName"></result>
    <result property="balance" column="balance"></result>
    <result property="uid" column="uid"></result>
    <association property="user" javaType="User" select="com.itstudy.test.dao.UserMapper.findOneById" column="uid" fetchType="lazy"/>
</resultMap>

select 属性为查询语句,

column 为复合传递的条件时传递的附表中主表的外键查询,相反如果是一对多查询传递的就是主表中放在附表中的外键字段

select必须为全限定路径,除非两个方法在同一个xml中。

一对多查询

在AccountMapper.xml中有

<!-- 根据条件查询一个订单 -->
<select id="findOneById" resultType="Account">
   select * from account where uid = #{uid}
</select>

UserMapper.xml中

<!-- 一对多复合查询 -->
<resultMap id="findOneGoMap" type="User">
    <id column="uid" property="uid"></id>
    <result column="name" property="name"></result>
    <result column="password" property="password"></result>
    <result column="email" property="email"></result>
    <result column="birthday" property="birthday"></result>
    <collection property="userAccount" javaType="java.util.List" ofType="Account" select="com.itstudy.test.dao.AccountMapper.findOneById" fetchType="lazy" column="uid"></collection>
</resultMap>
<select id="findGoId" resultMap="findOneGoMap">
    select * from `user` where uid = #{uid}
</select>

缓存简介,上面说的懒加载很好的节约了资源,提高了效率,缓存机制可以减少对数据库的访问次数,提高查询效率,但也不是所有数据都适合存储在缓存中。

修改少,查询多的数据适合存储在缓存中。

缓存就是拿空间换时间,消耗了内存节约了时间。

缓存详解 请看 https://blog.csdn.net/weixin_37139197/article/details/82908377

在这里只是解和上面案例简单介绍。

一级缓存自动开启

同一个 SqlSession 对象, 在参数和 SQL 完全一样的情况先, 只执行一次 SQL 语句,连返回结果集的实体都是同一个

可以使用属性关闭

<select id="selectByPrimaryKey" flushCache="true | false".....

二级缓存

在配置文件中配置开启全局缓存

<settings>
   <setting name="cacheEnabled" value="true"/>
</settings>
二级缓存存在于 SqlSessionFactory 生命周期中,同一个 SqlSessionFactory 查询时可查到缓存数据

 

posted @ 2019-10-08 20:08  一半人生  阅读(473)  评论(0编辑  收藏  举报