Mybatis小功能

1. choose、when、otherwise

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

如下列子,当**userId **条件满足时 查询所有的等于userId的数据 当userId不满足时 则根据otherwish下的条件进行查询。

<select id="selectOrders" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from orders where status=2
    <choose>
      <when test="userId!=null and userId!=0">
        and user_id=#{userId,jdbcType=BIGINT} order by create_time desc
      </when>
      <otherwise>
        order by create_time desc limit 10
      </otherwise>
    </choose>
  </select>

2. foreach

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符

<select id="selectForech" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from orders
    <where>
      <foreach collection="list" item="item" index="index" open="id in(" close=")" 					separator=",">
        #{item}
      </foreach>
    </where>
  </select>
  <select id="selectForechMap" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from orders
    <where>
      <foreach collection="key" item="item" index="index" open="id in(" close=")" 				separator=",">
        #{item}
      </foreach>
    </where>
  </select>

mapper层

List<Orders> selectForech(List list);

List<Orders> selectForechMap(HashMap map);

controller层

List<Integer> list = Arrays.asList(158, 160, 161);
HashMap<String, Object> map = new HashMap<>();
map.put("key",list);
List<Orders> orders = ordersMapper.selectForech(list);
System.out.println(orders);
System.out.println("____________________");
System.out.println(ordersMapper.selectForechMap(map));



Preparing: select id, order_num, pay_ano, user_id, shop_id, shop_name, commodity_nums, address_id, pay_type, pay_amount, status, remarks, pay_time, deal_time, deliver_time, create_time, update_time, express_name, express_number from orders WHERE id in( ? , ? , ? )
==> Parameters: 158(Integer), 160(Integer), 161(Integer)
<==    Columns: id, order_num, pay_ano, user_id, shop_id, shop_name, commodity_nums, address_id, pay_type, pay_amount, status, remarks, pay_time, deal_time, deliver_time, create_time, update_time, express_name, express_number
<==        Row: 158, 5330cf005c16d53a4d188089f4377ea8, 5332baef80393edd4690a0224a46f83d, 32, 18, 教育, 4, 39, null, 0.04, 0, null, null, null, null, 2021-05-19 09:53:31, 2021-05-19 17:12:53, null, 
<==        Row: 160, 4008332049fe0df846eaabd769399359, 4009554577f46cc54ee8ba69a3f0efe9, 36, 18,教育, 1, 38, 微信, 0.01, 2, null, 2021-05-19 10:40:26, null, 2021-05-19 11:14:45, 2021-05-19 10:40:08, 2021-05-19 11:14:45, null, 
<==        Row: 161, 4224927db7983f524be7b2aca3419b30, 44021f84e3c769fd4a3d97650592468d, 36, 18, 教育, 1, 38, 支付宝, 0.01, 2, null, 2021-05-19 10:44:21, null, 2021-05-19 11:09:14, 2021-05-19 10:42:25, 2021-05-19 11:09:14, 中通快递, 123456
<==      Total: 3

3.延迟加载

懒加载就是在需要查询关联信息的时候去加载查询语句,在不需要的时候就不去执行查询。

mybatis中,一对一关联的 association 和一对多的collection可以实现懒加载。

1. 开启懒加载

mybatis默认是没有开启懒加载的,要使用懒加载,需要先在全局配置中开启懒加载配置;

配置mybatis-config.xml

 <settings>
        <!--        开启懒加载(开启延迟加载)-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--        关闭实时加载 按需加载-->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--         防止默认的触发方法调用,导致延迟加载失效-->
        <setting name="lazyLoadTriggerMethods" value=""/>
        <!--        开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>
        <!--        设置日志类型-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

xm文件

<mapper namespace="com.example.springboot.mapper.UserBaseInfoMapper">
  <resultMap id="BaseResultMap" type="com.example.springboot.pojo.UserBaseInfo">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="username" jdbcType="VARCHAR" property="username" />
    <result column="session_id" jdbcType="VARCHAR" property="sessionId" />
    <result column="avatar" jdbcType="VARCHAR" property="avatar" />
    <result column="pwd" jdbcType="VARCHAR" property="pwd" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
    <result column="status" jdbcType="VARCHAR" property="status" />
    <!--fetchType用来设置数据加载方式,可选值有2种lazy和eager,分别为延迟加载和积极加载,这个配置会覆盖全lazyLoadingEnabled 配置-->
    <association property="orders"  column="id"
         fetchType="lazy"  select="selectOdersByUserId"></association>
  </resultMap>
  <resultMap id="ordersMap" type="com.example.springboot.pojo.Orders">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="order_num" jdbcType="VARCHAR" property="orderNum" />
    <result column="pay_ano" jdbcType="VARCHAR" property="payAno" />
    <result column="user_id" jdbcType="BIGINT" property="userId" />
    <result column="shop_id" jdbcType="BIGINT" property="shopId" />
    <result column="shop_name" jdbcType="VARCHAR" property="shopName" />
    <result column="commodity_nums" jdbcType="BIGINT" property="commodityNums" />
    <result column="address_id" jdbcType="BIGINT" property="addressId" />
    <result column="pay_type" jdbcType="VARCHAR" property="payType" />
    <result column="pay_amount" jdbcType="DECIMAL" property="payAmount" />
    <result column="status" jdbcType="TINYINT" property="status" />
    <result column="remarks" jdbcType="VARCHAR" property="remarks" />
    <result column="pay_time" jdbcType="TIMESTAMP" property="payTime" />
    <result column="deal_time" jdbcType="TIMESTAMP" property="dealTime" />
    <result column="deliver_time" jdbcType="TIMESTAMP" property="deliverTime" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
    <result column="express_name" jdbcType="VARCHAR" property="expressName" />
    <result column="express_number" jdbcType="VARCHAR" property="expressNumber" />
  </resultMap>

  <sql id="Base_Column_List">
    id, name, username, session_id, avatar, pwd, create_time, update_time, status
  </sql>

  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from user_base_info
    where id = #{id,jdbcType=BIGINT}
  </select>
  <select id="selectOdersByUserId" parameterType="java.lang.Long" resultMap="ordersMap">
    select * from Orders where user_id=#{id}
  </select>
  

select也可在不同的xml文件配置,需要写上方法的全限定类名

 <association property="orders"  column="id"
         select="com.example.springboot.mapper.OrdersMapperselectOdersByUserId"></association>
  </resultMap>
<!--collection 的属性ofType="com.example.springboot.pojo.Orders"-->
</--collection>
<collection property="orders"  column="id" ofType="com.example.springboot.pojo.Orders"
          select="com.example.springboot.mapper.OrdersMapper.selectOdersByUserId"></collection>
  </resultMap>

缓存

缓存是存在于内存中的临时数据。
使用缓存减少和数据库的交互次数,提高执行效率。

Mybatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制

1、适用于缓存
  • 经常查询并且不经常改变的;
  • 数据的正确与否对最终结果影响不大的;
2、不适用于缓存
  • 经常改变的数据;
  • 数据的正确与否对最终结果影响很大的;
  • 例如:商品的库存,银行的汇率,股市的牌价;
一级缓存

mybatis 的缓存分为2类,分别是一级缓存和二级缓存,一级缓存是默认开启的,它在一个sqlSession会话里面的所有查询操作都会保存到缓存中,一般来说一个请求中的所有增删改查操作都是在同一个sqlSession里面的,所以我们可以认为每个请求都有自己的一级缓存,如果同一个sqlSession会话中2 个查询中间有一个 insert 、update或delete 语句,那么之前查询的所有缓存都会清空;

在springboot+mybatis中使用一级缓存默认是失效的 需要在方法上开启事务

springboot集成mybatis,如果不开启事务,则每一个请求,都会开启一个sqlSession,执行完成后,sqlSession就会close,则在并发的请求下,虽然mapper是单例,但是能保证线程安全,当用了事务之后,当执行完service方法后,sqlSeesion才会close,所以一个请求service中多次调用,第二次调用可以从缓存中读取

@Test
	@Transactional
	void contextLoads(){
		//springboot集成mybatis,如果不开启事务,则每一个请求,都会开启一个sqlSession,执行完成后,sqlSession就会close,则在并发的请求下,虽然mapper是单例,但是能保证线程安全,当用了事务之后,当执行完service方法后,sqlSeesion才会close,所以一个请求service中多次调用,第二次调用可以从缓存中读取
		Orders orders = ordersMapper.selectByPrimaryKey(160l);
		
		Orders orders2 = ordersMapper.selectByPrimaryKey(160l);
		System.out.println(orders);
	}
二级缓存

二级缓存是全局的,也就是说;多个请求可以共用一个缓存,二级缓存需要手动开启,有2种方式配置二级缓存,

  • 缓存会先放在一级缓存中,当sqlSession会话提交或者关闭时才会将一级缓存刷新到二级缓存中;
  • 开启二级缓存后,用户查询时,会先去二级缓存中找,找不到在去一级缓存中找;

二级缓存显示开启配置 springboot中Mybatis的二级缓存默认为true

 <!--        开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>


2.在需要开启缓存的xml中添加 cache标签即可使用二级缓存

<cache>
</cache>

cache官方配置

  <cache  eviction="FIFO"
          flushInterval="60000"
          size="512"
          readOnly="true">
  </cache>

这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

可用的清除策略有:

  • LRU – 最近最少使用:移除最长时间不被使用的对象。
  • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  • SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
  • WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

默认的清除策略是 LRU。

flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

二级缓存是事务性的。这意味着,当 SqlSession 完成并提交时,或是完成并回滚,但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值