通过项目逐步深入了解Mybatis(四)

相关阅读:

1、通过项目逐步深入了解Mybatis<一>

2、通过项目逐步深入了解Mybatis<二>

3、通过项目逐步深入了解Mybatis<三>

本项目所有代码及文档都托管在 Github地址:https://github.com/zhisheng17/mybatis

延迟加载

什么是延迟加载?

resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。
需求:
如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。

延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高 数据库性能,因为查询单表要比关联查询多张表速度要快。

打开延迟加载开关

在mybatis核心配置文件中配置:

lazyLoadingEnabled、aggressiveLazyLoading

设置项描述允许值默认值
lazyLoadingEnabled全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。true falsefalse
aggressiveLazyLoading当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。true falsetrue
<settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/>
</settings>

使用 association 实现延迟加载

需求:查询订单并且关联查询用户信息

Mapper.xml

需要定义两个 mapper 的方法对应的 statement。

1、只查询订单信息

SQL 语句: select * from orders

在查询订单的 statement 中使用 association 去延迟加载(执行)下边的 statement (关联查询用户信息)

<!--查询订单并且关联查询用户信息,关联用户信息需要通过 association 延迟加载--><select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap">select * from orders</select>

2、关联查询用户信息

通过上面查询订单信息中的 user_id 来关联查询用户信息。使用 UserMapper.xml 中的 findUserById

SQL语句:select * from user where id = user_id

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

上边先去执行 findOrdersUserLazyLoading,当需要去查询用户的时候再去执行 findUserById ,通过 resultMap的定义将延迟加载执行配置起来。也就是通过 resultMap 去加载 UserMapper.xml 文件中的 select = findUserById

延迟加载的 resultMap

<!--定义 关联用户信息(通过 association 延迟加载)的resultMap--><resultMap id="OrdersUserLazyLoadingResultMap" type="cn.zhisheng.mybatis.po.Orders"><!--对订单信息映射--><id column="id" property="id"/><result column="user_id" property="userId"/><result column="number" property="number"/><result column="createtime" property="createtime"/><result column="note" property="note"/><!-- 实现对用户信息进行延迟加载select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement)要使用userMapper.xml中findUserById完成根据用户id(user_id)用户信息的查询,如果findUserById不在本mapper中需要前边加namespacecolumn:订单信息中关联用户信息查询的列,是user_id关联查询的sql理解为:SELECT orders.*,(SELECT username FROM USER WHERE orders.user_id = user.id)username,(SELECT sex FROM USER WHERE orders.user_id = user.id)sexFROM orders--><association property="user" javaType="cn.zhisheng.mybatis.po.User" select="cn.zhisheng.mybatis.mapper.UserMapper.findUserById" column="user_id"></association></resultMap>

OrderMapperCustom.java

public List<Orders> findOrdersUserLazyLoading() throws Exception;

测试代码:

@Testpublic void testFindOrdersUserLazyLoading() throws Exception{SqlSession sqlSession = sqlSessionFactory.openSession();//创建OrdersMapperCustom对象,mybatis自动生成代理对象OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);//查询订单信息List<Orders> list = ordersMapperCustom.findOrdersUserLazyLoading();//遍历所查询的的订单信息for (Orders orders : list){//查询用户信息User user = orders.getUser();System.out.println(user);}sqlSession.close();}

测试结果:

整个延迟加载的思路:

1、执行上边mapper方法(findOrdersUserLazyLoading),内部去调用cn.zhisheng.mybatis.mapper.OrdersMapperCustom 中的 findOrdersUserLazyLoading 只查询 orders 信息(单表)。

2、在程序中去遍历上一步骤查询出的 List<Orders>,当我们调用 Orders 中的 getUser 方法时,开始进行延迟加载。

3、延迟加载,去调用 UserMapper.xml 中 findUserbyId 这个方法获取用户信息。

思考:

不使用 mybatis 提供的 association 及 collection 中的延迟加载功能,如何实现延迟加载??

实现方法如下:

定义两个mapper方法:

1、查询订单列表

2、根据用户id查询用户信息

实现思路:

先去查询第一个mapper方法,获取订单信息列表

在程序中(service),按需去调用第二个mapper方法去查询用户信息。

总之:

使用延迟加载方法,先去查询 简单的 sql(最好单表,也可以关联查询),再去按需要加载关联查询的其它信息。

一对多延迟加载

上面的那个案例是一对一延迟加载,那么如果我们想一对多进行延迟加载呢,其实也是很简单的。

一对多延迟加载的方法同一对一延迟加载,在collection标签中配置select内容。

延迟加载总结:

作用:

当需要查询关联信息时再去数据库查询,默认不去关联查询,提高数据库性能。
只有使用resultMap支持延迟加载设置。

场合:

当只有部分记录需要关联查询其它信息时,此时可按需延迟加载,需要关联查询时再向数据库发出sql,以提高数据库性能。

当全部需要关联查询信息时,此时不用延迟加载,直接将关联查询信息全部返回即可,可使用resultType或resultMap完成映射。

查询缓存

什么是查询缓存?

mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。

mybaits提供一级缓存,和二级缓存。

  • 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

  • 二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

为什么要用缓存?

如果缓存中有数据就不用从数据库中获取,大大提高系统性能。

一级缓存

工作原理

第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。

得到用户信息,将用户信息存储到一级缓存中。

如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

一级缓存测试

Mybatis 默认支持一级缓存,不需要在配置文件中配置。

所以我们直接按照上面的步骤进行测试:

//一级缓存测试@Testpublic void  testCache1() throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();//创建UserMapper对象,mybatis自动生成代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//查询使用的是同一个session//第一次发起请求,查询Id 为1的用户信息User user1 = userMapper.findUserById(1);System.out.println(user1);//第二次发起请求,查询Id 为1的用户信息User user2 = userMapper.findUserById(1);System.out.println(user2);sqlSession.close();}

通过结果可以看出第二次没有发出sql查询请求,

所以我们需要在中间执行 commit 操作

//如果sqlSession去执行commit操作(执行插入、更新、删除),
// 清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
//更新user1的信息,
user1.setUsername("李飞");
//user1.setSex("男");
//user1.setAddress("北京");
userMapper.updateUserById(user1);
//提交事务,才会去清空缓存
sqlSession.commit();

测试

一级缓存应用

正式开发,是将 mybatis 和 spring 进行整合开发,事务控制在 service 中。

一个 service 方法中包括很多 mapper 方法调用。

service{

     //开始执行时,开启事务,创建SqlSession对象//第一次调用mapper的方法findUserById(1)//第二次调用mapper的方法findUserById(1),从一级缓存中取数据//方法结束,sqlSession关闭

}

如果是执行两次service调用查询相同的用户信息,不走一级缓存,因为session方法结束,sqlSession就关闭,一级缓存就清空。

二级缓存

原理

首先开启mybatis的二级缓存。

sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

如果SqlSession3去执行相同 mapper下sql,执行commit提交,清空该 mapper下的二级缓存区域的数据。

sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。

UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。

每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。

开启二级缓存

mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存

在 SqlMapConfig.xml 开启二级开关

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

然后在你的 Mapper 映射文件中添加一行: <cache/> ,表示此 mapper 开启二级缓存。

调用 pojo 类实现序列化接口

二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操作(因为二级缓存数据存储介质多种多样,在内存不一样),注意如果存在父类、成员pojo都需要实现序列化接口。

public class Orders implements Serializable
public class User implements Serializable

测试

//二级缓存测试@Testpublic void testCache2() throws Exception{SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();SqlSession sqlSession3 = sqlSessionFactory.openSession();//创建UserMapper对象,mybatis自动生成代理对象UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);//sqlSession1 执行查询 写入缓存(第一次查询请求)User user1 = userMapper1.findUserById(1);System.out.println(user1);sqlSession1.close();//sqlSession3  执行提交  清空缓存UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);User user3 = userMapper3.findUserById(1);user3.setSex("女");user3.setAddress("山东济南");user3.setUsername("崔建");userMapper3.updateUserById(user3);//提交事务,清空缓存sqlSession3.commit();sqlSession3.close();//sqlSession2 执行查询(第二次查询请求)UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);User user2 = userMapper2.findUserById(1);System.out.println(user2);sqlSession2.close();}

结果

useCache 配置

在 statement 中设置 useCache=false 可以禁用当前 select 语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

<select id="findUserById" parameterType="int" resultType="user" useCache="false">

总结:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。

刷新缓存(清空缓存)

在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。

设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

如下:

<insert id="insetrUser" parameterType="cn.zhisheng.mybatis.po.User" flushCache="true">

一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。

Mybatis Cache参数

flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。

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

如下例子:

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

这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:

  1. LRU – 最近最少使用的:移除最长时间不被使用的对象。

  2. FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

  3. SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

  4. WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

Mybatis 整合 ehcache

ehcache 是一个分布式缓存框架。

分布缓存

我们系统为了提高系统并发,性能、一般对系统进行分布式部署(集群部署方式)

不使用分布缓存,缓存的数据在各各服务单独存储,不方便系统 开发。所以要使用分布式缓存对缓存数据进行集中管理。

mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合。

整合方法

mybatis 提供了一个二级缓存 cache 接口(org.apache.ibatis.cache 下的 Cache),如果要实现自己的缓存逻辑,实现cache接口开发即可。

import java.util.concurrent.locks.ReadWriteLock;
public interface Cache {String getId();void putObject(Object var1, Object var2);Object getObject(Object var1);Object removeObject(Object var1);void clear();int getSize();ReadWriteLock getReadWriteLock();
}

mybatis和ehcache整合,mybatis 和 ehcache 整合包中提供了一个 cache 接口的实现类(org.apache.ibatis.cache.impl 下的 PerpetualCache)。

package org.apache.ibatis.cache.impl;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheException;
public class PerpetualCache implements Cache {private String id;private Map<Object, Object> cache = new HashMap();public PerpetualCache(String id) {this.id = id;}public String getId() {return this.id;}public int getSize() {return this.cache.size();}public void putObject(Object key, Object value) {this.cache.put(key, value);}public Object getObject(Object key) {return this.cache.get(key);}public Object removeObject(Object key) {return this.cache.remove(key);}public void clear() {this.cache.clear();}public ReadWriteLock getReadWriteLock() {return null;}public boolean equals(Object o) {if(this.getId() == null) {throw new CacheException("Cache instances require an ID.");} else if(this == o) {return true;} else if(!(o instanceof Cache)) {return false;} else {Cache otherCache = (Cache)o;return this.getId().equals(otherCache.getId());}}public int hashCode() {if(this.getId() == null) {throw new CacheException("Cache instances require an ID.");} else {return this.getId().hashCode();}}
}

通过实现 Cache 接口可以实现 mybatis 缓存数据通过其它缓存数据库整合,mybatis 的特长是sql操作,缓存数据的管理不是 mybatis 的特长,为了提高缓存的性能将 mybatis 和第三方的缓存数据库整合,比如 ehcache、memcache、redis等。

  • 引入依赖包

ehcache-core-2.6.5.jarmybatis-ehcache-1.0.2.jar

  • 引入缓存配置文件

classpath下添加:ehcache.xml

内容如下:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"><diskStore path="C:\JetBrains\IDEAProject\ehcache" /><defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000"eternal="false" overflowToDisk="false" timeToIdleSeconds="120"timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"></defaultCache>
</ehcache>

属性说明:

  • diskStore:指定数据在磁盘中的存储位置。

  • defaultCache:当借助 CacheManager.add("demoCache") 创建Cache时,EhCache 便会采用<defalutCache/>指定的的管理策略

以下属性是必须的:

  • maxElementsInMemory - 在内存中缓存的element的最大数目

  • maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大

  • eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断

  • overflowToDisk- 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上

以下属性是可选的:

  • timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大

  • timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大

       diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
    
  • diskPersistent- 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。

  • diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作

  • memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)

  • 开启ehcache缓存

EhcacheCache 是ehcache对Cache接口的实现;修改mapper.xml文件,在cache中指定EhcacheCache。

根据需求调整缓存参数:

<cache type="org.mybatis.caches.ehcache.EhcacheCache" > <property name="timeToIdleSeconds" value="3600"/><property name="timeToLiveSeconds" value="3600"/><!-- 同ehcache参数maxElementsInMemory --><property name="maxEntriesLocalHeap" value="1000"/><!-- 同ehcache参数maxElementsOnDisk --><property name="maxEntriesLocalDisk" value="10000000"/><property name="memoryStoreEvictionPolicy" value="LRU"/></cache>

测试 :(这命中率就代表成功将ehcache 与 mybatis 整合了)

应用场景

对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用 mybatis 二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。

实现方法如下:通过设置刷新间隔时间,由 mybatis 每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔 flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

局限性

mybatis 二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用 mybatis 的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为 mybaits 的二级缓存区域以 mapper 为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283296.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读两本敦煌书杂记-敦煌的历史(一)

前两天看了樊锦诗院长的讲座&#xff0c;八十几岁的高龄还讲的兴致盎然&#xff0c;虽然全长两个多小时但感觉一点不嫌长&#xff0c;听完深受感动。意犹未尽&#xff0c;又迫不及待的买了几本书来读。一本是《灿烂佛宫》&#xff0c;一本是《报恩父母经典故事》。因为我自己从…

在anaconda中安装tensorflow-GPU版本

在anaconda中安装tensorflow-GPU版本 第一步&#xff1a;去anaconda官网下载&#xff0c;我下载的是anaconda (python3.7版本&#xff09; anaconda下载链接&#xff1a;点击link 进去之后网页最下面有要下载的版本 安装的具体步骤&#xff1a;点击 link 第二步&#xff1a;…

云服务远程登录---设置安全组

对于小白来说购买了云服务不知道怎么开放端口和用xsell远程连接下面是步骤&#xff1a; 下面就可以玩耍了转载于:https://www.cnblogs.com/zhaojingyu/p/9021068.html

高程数据处理_珠峰长高了吗?新高程怎么算出来的?揭秘

珠穆朗玛峰是世界上海拔最高的山峰&#xff0c;被称为世界第三极&#xff0c;是亚洲的水塔。12月8日&#xff0c;珠穆朗玛峰最新高程公布&#xff0c;为8848.86米。珠峰长高了吗&#xff1f;怎么测算出来的&#xff1f;和以往的测量相比&#xff0c;“新”在哪里&#xff1f;就…

微服务框架开发(二)—扩展spring schema

2019独角兽企业重金招聘Python工程师标准>>> 一、实体bean的定义 回顾一下我们需要定义的4个标签 定义注册中心标签&#xff1a;<xmen:registry name"registry" regProtocol"zookeeper" address"127.0.0.1:2181" connectTimeout&q…

如何找tensorflow-gpu版本对应的cuda和cudnn

第一步 先创建一个虚拟环境&#xff08;我是在anaconda Prompt中创建&#xff09;&#xff1a;conda create -n TF1.14 python3.6 第二步 进入虚拟环境conda activate TF1.14 第三步 安装tensorflow-gpu版本 pip install tensorflow-gpu1.14.0 -i HTTPS://pypi.doubanio…

基于干净语言和好奇心的敏捷指导

\关键要点\\通过简单的问题可以挖掘出产品中包含的真正有价值的信息&#xff0c;以及我们所期望的合作方式。\\t在以“干净问题”为基础的文化中&#xff0c;没有问题会遭到嘲笑&#xff0c;而且不存在“愚蠢”的问题。\\t“尽其所能地工作”和“干净反馈”等练习可以帮助敏捷团…

origin如何绘制双y轴曲线_Origin用矩阵绘制多层曲面映射图

点击上方关注点击下方点赞【导读】怎样绘制多曲面映射图&#xff1f;1.矩阵数据的准备1.1 XYYYY型数据我们在实验中得到一张Excel表格一列X表示电场强度&#xff0c;负载量不同的多列Y又分为Pm、Pr两组。那么我们需要分别构造Pm和Pr两组XYYYY型数据表。那么全选Pr表中的XYYYY型…

北京大学Tensorflow2.0笔记

激活函数 目前很少用这个激活函数&#xff0c;因为在深度神经网络中更新参数时需要从输出层到输入层逐层进行链式求导&#xff0c;而sigmoid函数倒数值为0-0.25之间&#xff0c;链式求导需要多层导数连续相乘&#xff0c;会出现多个0-0.25之间的连续相乘&#xff0c;结果趋于零…

开源新工具 Azure Developer CLI

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;5分钟)翻译自 Savannah Ostrowski 的博客今天&#xff0c;我们很高兴地宣布 Azure Developer CLI (azd) 公共预览版——一种新的开源工具&#xff0c;可加快入门Azure 所需的时间。Azure Developer CLI 提供了对开发者…

MapReduce中的InputFormat(1)概述

1 概念InputFormat用于描述输入数据的格式&#xff0c;提供以下两个功能&#xff1a;A、数据切分&#xff1a;按照某种策略将输入的数据切分成若干split&#xff0c;以便确定Map Task个数&#xff0c;以及对应的Split。B、提供数据&#xff1a;为Mapper提供输入数据&#xff0c…

在anaconda中运行jupyter notebook,无法自动打开浏览器的解决方案,亲测100%有效

运行jupyter notebook&#xff0c;无法自动打开浏览器的解决方案 第一步 找到 Jupyter_notebook_config.py文件&#xff0c;无论你anaconda装在哪个盘&#xff0c;这个文件一般都在C盘&#xff0c;我的在C:\Users\wyf峰.jupyter 如果没有可以在anaconda prompt中输入以下语句…

本地配置_Hadoop本地模式的安装配置

Hadoop 是一个由 Apache 基金会所开发的分布式系统基础架构&#xff0c;它可以使用户在不了解分布式底层细节的情況下开发分布式程序&#xff0c;充分利用集群的威力进行高速运算和存储。从其定义就可以发现&#xff0c;它解決了两大问题&#xff1a;大数据存储、大数据分析。也…

基于 Filter 实现条件路由

基于 filter 实现条件路由Intro在我们的项目有几个测试用的接口&#xff0c;有的接口我们往往不想在生产环境上使用&#xff0c;于是会在代码里判断当前环境是不是生产环境&#xff0c;如果不是生产环境才允许执行&#xff0c;否则就返回一个错误&#xff0c;这样的接口多了之后…

ORM框架通过映射(反射)获取数据库的数据

ORM&#xff08;Object Relational Mapping&#xff09;框架采用元数据来描述对象一关系映射细节&#xff0c;元数据一般采用XML格式&#xff0c;并且存放在专门的对象一映射文件中。只要提供了持久化类与表的映射关系&#xff0c;ORM框架在运行时就能参照映射文件的信息&#…

找不到r低版本_R 语言与数据挖掘直播班开始招生,生信分析帮你发高分文章

数据单薄很难支撑文章内容&#xff1f;数据有了不知道怎么处理作出高级的图片&#xff1f;这个时候需要的是生信分析——深度的数据挖掘和分析处理&#xff0c;可以帮助临床医生通过数据处理得到自己想要的信息&#xff0c;更快速地发文章。学习哪种生信分析的工具&#xff1f;…

读两本敦煌书杂记-敦煌由盛转衰(二)

公元420-589年&#xff0c;中国分为南北两个部分&#xff08;史称魏晋南北朝&#xff0c;由西晋末年八王之乱引起&#xff0c;北方游牧少数民族趁机侵扰中原&#xff0c;并先后建立多个少数民族政权&#xff0c;又称“五胡乱华”。“五胡”主要指匈奴、鲜卑、羯、羌、氐五个胡人…

第三方app_为什么第三方APP不能下载呢?

这些年科学技术发展日新月异&#xff0c;信息技术和网络技术也层出不穷&#xff0c;大众出行工具的汽车电器化集成度越来越高&#xff0c;汽车上娱乐主机的智能化和网络化程度也越来越高&#xff0c;汽车娱乐主机也成了人民除手机外的第二个娱乐工具&#xff0c;用惯了手机娱乐…

WPF效果第一百九十七篇之Path范围内拖拽

前面效果中分享了彩色马蹄图的效果;这不今天再次在马蹄图的基础上,实现只能在Path内的拖拽效果;闲话不多扯直接看效果:1、关于拖拽顶点实现色域范围选择,参考:https://www.codeproject.com/Tips/828310/The-simplest-WPF-diagram-designer-part2、通过Blend绘制了色度图中间区域…

PHP面向对象常见的关键字和魔术方法

在PHP5的面向对象程序设计中提供了一些常见的关键字&#xff0c;用来修饰类、成员属性或成员方法&#xff0c;使他们具有特定的功能&#xff0c;例如final、static、const等关键字。还有一些比较实用的魔术方法&#xff0c;用来提高类或对象的应用能力&#xff0c;例如__call()…