Mybatis學(xué)習(xí)記錄

1. mybatis的基本概念

MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL稠曼、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集堤如。MyBatis 可以使用簡(jiǎn)單的 XML 或注解來(lái)配置和映射原生信息蒲列,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄。

上面是mybatis官方介紹搀罢,從介紹我們可以得知mybatis有以下特點(diǎn):

它是一個(gè)持久化框架

它支持sql蝗岖、存儲(chǔ)過(guò)程、高級(jí)映射

它支持手動(dòng)設(shè)置參數(shù)并且分裝結(jié)果集

它支持xml和注解兩種配置方式

以下為mybatis內(nèi)的一些基本概念:

SqlSessionFactory:SqlSession類的工廠類

SqlSession:數(shù)據(jù)庫(kù)會(huì)話類榔至,為用戶提供數(shù)據(jù)庫(kù)操作方法

Executor:數(shù)據(jù)庫(kù)操作的執(zhí)行器抵赢,SqlSession通過(guò)Executor操作數(shù)據(jù)庫(kù)

MappedStatement:是一個(gè)sql操作的首相

映射接口:具體的業(yè)務(wù)模塊接口,映射接口不需要有實(shí)現(xiàn)類唧取,接口內(nèi)定義了一些列方法铅鲤,每個(gè)方法對(duì)應(yīng)一個(gè)sql操作,方法名就是sql操作的id

映射文件:當(dāng)配置方式為xml時(shí)枫弟,可以將sql寫在xml配置文件中邢享,一個(gè)映射文件對(duì)應(yīng)一個(gè)映射接口

Cache:mybatis內(nèi)部緩存實(shí)現(xiàn)

Configuration:全局配置信息(以及配置信息解析的結(jié)果)存放處,該實(shí)例全局共享淡诗,該實(shí)例是SqlSessionFactory的屬性

2. mybatis如何構(gòu)建和執(zhí)行的

那mybatis是如果構(gòu)建和執(zhí)行的呢骇塘,先看一個(gè)小例子(這里以xml配置方式為例):

創(chuàng)建一個(gè)maven項(xiàng)目

引入mybatis和mysql連接工具依賴

org.mybatismybatis3.4.5mysqlmysql-connector-java6.0.6復(fù)制代碼

編寫mybatis配置文件

<?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"><!-- 關(guān)閉一級(jí)緩存 -->復(fù)制代碼

編寫映射接口

publicinterfaceUserMapper{ListselectUser();}復(fù)制代碼

編寫映射xml文件(resources/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">select * from user

編寫啟動(dòng)類

publicclassApp{publicstaticvoidmain(String[] args)throwsException{? ? ? ? SqlSessionFactoryBuilder factoryBuilder =newSqlSessionFactoryBuilder();? ? ? ? InputStream resource = Resources.getResourceAsStream("config.xml");? ? ? ? SqlSessionFactory sessionFactory = factoryBuilder.build(resource);? ? ? ? SqlSession sqlSession = sessionFactory.openSession();/* 這里通過(guò)jdk的動(dòng)態(tài)代理獲取UserMapper接口的代理類 */UserMapper userMapper = sqlSession.getMapper(UserMapper.class);? ? ? ? List list = userMapper.selectUser();? ? ? ? System.out.println(list.size());? ? }}

以上就是搭建純mybatis運(yùn)行環(huán)境的過(guò)程,程序配置過(guò)程不詳述韩容,這里說(shuō)一下mybatis的啟動(dòng)構(gòu)建和執(zhí)行過(guò)程款违。

先是創(chuàng)建SqlSessionFactoryBuilder實(shí)例,改實(shí)例的唯一作用就是用來(lái)構(gòu)建SqlSessionFactory的群凶,一但創(chuàng)建了SqlSessionFactory實(shí)例SqlSessionFactoryBuilder實(shí)例就沒(méi)用了插爹。構(gòu)建SqlSessionFactory的過(guò)程如下:

加載mybatis配置文件

(XMLConfigBuilder.parse)解析配置文件:解析過(guò)程是將xml配置文件內(nèi)的所有配置標(biāo)簽都解析并包括

<properties/>

<settings/>

<typeAliases/>

<plugins/>

<objectFactory/>

<objectWrapperFactory/>

<reflectorFactory/>

<environments/>

<databaseIdProvider/>

<typeHandlers/>

<mappers/>

解析每個(gè)標(biāo)簽調(diào)用不同的方法處理該標(biāo)簽的配置,例如解析標(biāo)簽是會(huì)把內(nèi)配置的所有映射記錄解析將mapper記錄添加到Configuration的MapperRegistry中去请梢,并且將對(duì)應(yīng)mapper配置文件里的所有的sql操作解析成MapperStatement(XMLMapperBuilder.parse)赠尾,同時(shí)也會(huì)解析resultMap和緩存配置。

解析xml配置文件最終會(huì)將所有配置信息放到Configuration實(shí)例中去毅弧,該實(shí)例是全局共享的萍虽,后續(xù)獲取Mapper接口代理、獲取MapperStatement形真、獲取Executor都會(huì)從這個(gè)Configuration實(shí)例中獲取杉编。

解析完之后創(chuàng)建DefaultSqlSessionFactory實(shí)例,這里創(chuàng)建DefaultSqlSessionFactory實(shí)例比價(jià)簡(jiǎn)單就是調(diào)用一個(gè)參數(shù)為Configuration的構(gòu)造函數(shù)即可咆霜,因?yàn)樗械男畔⒍家呀?jīng)存放到Configuration實(shí)例中去了

獲取SqlSession會(huì)話對(duì)象邓馒,調(diào)用SqlSessionFactory.open()方法即可,該方法最終會(huì)調(diào)用SqlSessionFactory.openSessionFromDataSource方法根據(jù)Configuration配置信息創(chuàng)建一個(gè)SqlSession實(shí)例蛾坯。

有了SqlSession實(shí)例后光酣,獲取映射接口的代理類,例如這里的sqlSession.getMapper(UserMapper.class)脉课,這里其實(shí)就是通過(guò)jdk的動(dòng)態(tài)代理獲取得到UserMapper接口的代理類救军,實(shí)際代理的InvocationHandler是MapperProxy财异,在MapperProxy.invoke方法中會(huì)攔截映射接口的方法調(diào)用,然后創(chuàng)建(可能會(huì)被緩存)MapperMethod實(shí)例通過(guò)執(zhí)行MapperMethod.execute方法執(zhí)行sql操作唱遭,接著會(huì)調(diào)用SqlSession內(nèi)的一系列方法如selectList戳寸、insert、query等拷泽,根據(jù)調(diào)用的接口和方法組合的全限定名例如:com.test.UserMapper.getUser來(lái)獲取MappedStatement疫鹊,最后通過(guò)Executor來(lái)作sql的操作(當(dāng)然其內(nèi)部也有些封裝執(zhí)行操作,詳情可看Executor的實(shí)現(xiàn)類BaseExecutor司致、CachingExecutor的源碼)拆吆。

Executor執(zhí)行sql的操作的過(guò)程,會(huì)將sql執(zhí)行的結(jié)果例如是insert脂矫、update枣耀、delete操作會(huì)返回執(zhí)行的影響的條數(shù),如果是query操作會(huì)將結(jié)果封裝成對(duì)應(yīng)的sql配置文件配置的類型(如pojo類型庭再、map奕枢、resultMap等)返回List或者單個(gè)對(duì)象并返回。這里mybatis大量使用了范型佩微。

以上就是Mybatis大致的啟動(dòng)構(gòu)建和執(zhí)行過(guò)程缝彬,只能將主要的節(jié)點(diǎn)描述,很多細(xì)節(jié)還需閱讀源碼哺眯。

下圖為mybatis啟動(dòng)示意圖:

3. mybatis的緩存

mybatis內(nèi)置了兩種緩存谷浅,一種是一級(jí)緩存(默認(rèn)開(kāi)啟),一種是二級(jí)緩存(默認(rèn)開(kāi)啟)奶卓,一級(jí)緩存是會(huì)話級(jí)別的也就是一個(gè)SqlSession實(shí)例內(nèi)的緩存一疯,而二級(jí)緩存是namespace級(jí)別的,所謂namespace就是一個(gè)映射接口的范圍夺姑,也就是說(shuō)如果開(kāi)啟了二級(jí)緩存那么多個(gè)會(huì)話如果調(diào)用的是同一個(gè)映射接口那么是有可能命中二級(jí)緩存的墩邀。下面詳細(xì)描述。

一級(jí)緩存:在上一部分我們知道對(duì)于SqlSession里的一系列操作方法盏浙,實(shí)際上最終會(huì)調(diào)用Executor執(zhí)行器內(nèi)的方法來(lái)進(jìn)行sql操作眉睹,Executor在mybatis種提供了幾個(gè)實(shí)現(xiàn)類,在不開(kāi)啟二級(jí)緩存的情況下默認(rèn)使用SimpleExecutor實(shí)現(xiàn)類废膘,SimpleExecutor是集成的BaseExecutor抽象類竹海,大部分的方法已在BaseExecutor實(shí)現(xiàn),我們關(guān)注BaseExecutor丐黄,當(dāng)作查詢操作的時(shí)候最終會(huì)執(zhí)行BaseExecutor.query方法斋配,在BaseExecutor類的152行有這樣的代碼list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;這里就是一級(jí)緩存實(shí)現(xiàn)的地方,即一級(jí)緩存是保存在BaseExecutor內(nèi)部屬性localCache中,而localCache其實(shí)就是個(gè)PerpetualCache而該類是mybatis緩存的一個(gè)實(shí)現(xiàn)類艰争,下鉆到PerpetualCache內(nèi)可以發(fā)現(xiàn)其內(nèi)部有個(gè)類型為Map的cache屬性其中key為CacheKey值就是查詢結(jié)果坏瞄。當(dāng)執(zhí)行了update、commit等方法后一級(jí)緩存會(huì)被清空甩卓。我們可以看到鸠匀,一級(jí)緩存只提供了簡(jiǎn)單的緩存更新的策略,如果使用一個(gè)SqlSession實(shí)例作同一個(gè)查詢不管查詢多少此其結(jié)果都不會(huì)變猛频,這就有可能出現(xiàn)臟數(shù)據(jù),所以需要斟酌使用一級(jí)緩存蛛勉,如果對(duì)數(shù)據(jù)實(shí)時(shí)性要求高可以在mybatis配置文件配置標(biāo)簽里設(shè)置<setting name="localCacheScope" value="STATEMENT"/>來(lái)關(guān)閉一級(jí)緩存鹿寻。

二級(jí)緩存:二級(jí)緩存是默認(rèn)開(kāi)啟的,如果要關(guān)閉可以在mybatis配置文件配置標(biāo)簽里設(shè)置<setting name="cacheEnabled" value="false"/>诽凌,開(kāi)啟二級(jí)緩存后SqlSession內(nèi)的Executor為CachingExecutor毡熏,實(shí)際CachingExecutor是使用裝飾器模式將包了一層,具體sql操作委托給其他的Executor執(zhí)行(其實(shí)默認(rèn)是委托給SimpleExecutor)侣诵,CachingExecutor只做二級(jí)緩存的處理痢法。源碼CachingExecutor第95行,在執(zhí)行查詢之前先從MappedStatement中獲取cache(如果對(duì)應(yīng)mapper映射文件中未配置那么此處的cache是空的杜顺,其實(shí)這里的cache在mybatis啟動(dòng)構(gòu)建解析配置文件的時(shí)候就已經(jīng)創(chuàng)建好了财搁,這個(gè)cache實(shí)例是和namespace一一對(duì)應(yīng)的)。如果部位空那么就從cache中獲取值躬络。但是這里不是直接從cache中獲取值而是通過(guò)CacheExecutor內(nèi)部的TransactionalCacheManager來(lái)獲取尖奔,之所以這樣是為了保證事務(wù)成功或失敗后緩存的正常保存和清理。例如這里如果開(kāi)啟二級(jí)緩存做一次查詢其實(shí)沒(méi)發(fā)真正保存緩存穷当,此時(shí)緩存是保存在TransactionalCache中的提茁,TransactionalCache內(nèi)保存了所有本次事務(wù)操作需有需要緩存的值,只有調(diào)用SqlSession.commit方法后將commit傳遞到TransactionalCache.commit才能真正保存緩存到namespace的cache實(shí)例中馁菜。在作insert茴扁、update、delete時(shí)二級(jí)緩存也會(huì)被清除汪疮,想比一級(jí)緩存二級(jí)緩存有淘汰策略峭火,默認(rèn)策略上LRU(淘汰最急最少使用),可以在映射配置文件的配置標(biāo)簽中自定義智嚷,除此之外還有:

FIFO:先進(jìn)先出:按對(duì)象進(jìn)入緩存的順序來(lái)移除它們

SOFT:軟引用:移除基于垃圾回收器狀態(tài)和軟引用規(guī)則的對(duì)象

WEAK:弱引用:更積極地移除基于垃圾收集器狀態(tài)和弱引用規(guī)則的對(duì)象

例如:

復(fù)制代碼

Cache:Cache是mybatis在一二級(jí)緩存是對(duì)緩存的抽象躲胳,Cache接口有一系列的實(shí)現(xiàn)類,這些實(shí)現(xiàn)類使用裝飾器模式來(lái)實(shí)現(xiàn)對(duì)不能緩存功能的包裝和功能疊加纤勒。

4. mybatis的插件系統(tǒng)

MyBatis 允許你在已映射語(yǔ)句執(zhí)行過(guò)程中的某一點(diǎn)進(jìn)行攔截調(diào)用坯苹。默認(rèn)情況下,MyBatis 允許使用插件來(lái)攔截的方法調(diào)用包括:

Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)

ParameterHandler (getParameterObject, setParameters)

ResultSetHandler (handleResultSets, handleOutputParameters)

StatementHandler (prepare, parameterize, batch, update, query)

以上是官方的對(duì)plugin的介紹摇天,本質(zhì)上plugin在sql操作的執(zhí)行周期中作用的粹湃,可以作用的點(diǎn)包括Executor恐仑、ParameterHandler、ResultSetHandler为鳄、StatementHandler內(nèi)部的一系列方法裳仆。mybatis通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)對(duì)作用點(diǎn)前后的自定義操作。在Configuration中有個(gè)interceptorChain屬性孤钦,即插件作用鏈歧斟,在Configuration中newParameterHandler、newResultSetHandler偏形、newStatementHandler静袖、newExecutor這些方法都會(huì)調(diào)用InterceptorChain.pluginAll方法通過(guò)動(dòng)態(tài)代理的方式將每個(gè)插件穿起來(lái),生成插件動(dòng)態(tài)代理鏈?zhǔn)峭ㄟ^(guò)插件工具類Plugin來(lái)實(shí)現(xiàn)俊扭,調(diào)用Plugin.wrap這個(gè)靜態(tài)方法來(lái)創(chuàng)建代理類队橙,代理InvocationHandler類就是Plugin(Plugin本身實(shí)現(xiàn)了InvocationHandler接口),當(dāng)然在創(chuàng)建插件代理類的過(guò)程中還會(huì)判斷插件類的簽名信息即插件類的@Intercepts注解配置信息萨惑,該配置信息里配置了該插件的作用點(diǎn)(實(shí)際上就是作用的函數(shù)調(diào)用點(diǎn))捐康。例如我們想把查詢出來(lái)為L(zhǎng)ist<Map>類型的結(jié)果內(nèi)部的Map字段轉(zhuǎn)成駝峰形式(如:user_name轉(zhuǎn)成userName)我們可以使用插件來(lái)實(shí)現(xiàn)。

@Intercepts({@Signature(? ? ? ? type= ResultSetHandler.class,? ? ? ? method ="handleResultSets",? ? ? ? args = {Statement.class})})publicclassMyPluginimplementsInterceptor{@Override@SuppressWarnings("unchecked")publicObjectintercept(Invocation invocation)throwsThrowable{? ? ? ? List result = (List) invocation.proceed();if(result !=null&& result.size() >0) {if(result.get(0)instanceofMap) {? ? ? ? ? ? ? ? List reList =newArrayList();for(Map el : (List) result) {? ? ? ? ? ? ? ? ? ? Map map =newHashMap();for(String key : (Set) el.keySet()) {? ? ? ? ? ? ? ? ? ? ? ? map.put(getCamelKey(key), el.get(key));? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? reList.add(map);? ? ? ? ? ? ? ? }returnreList;? ? ? ? ? ? }? ? ? ? }returnresult;? ? }@OverridepublicObjectplugin(Object target){returnPlugin.wrap(target,this);? ? }@OverridepublicvoidsetProperties(Properties properties){? ? }privateStringgetCamelKey(String key){? ? ? ? String[] split = key.split("_");? ? ? ? String camelKey ="";for(inti =0; i < split.length; i++) {if(i !=0) camelKey += split[i].substring(0,1).toUpperCase() + split[i].substring(1, split[i].length());elsecamelKey += split[i];? ? ? ? }returncamelKey;? ? }}

5. mybatis的日志系統(tǒng)

Mybatis 的內(nèi)置日志工廠提供日志功能庸蔼,內(nèi)置日志工廠將日志交給以下其中一種工具作代理:

SLF4J

Apache Commons Logging

Log4j 2

Log4j

JDK logging

實(shí)際mybatis只提供了一個(gè)日志工廠LogFactory解总,mybatis通過(guò)日志工廠獲取日志對(duì)象,mybatis本身不提供日志實(shí)現(xiàn)姐仅,具體的日志交給第三方日志框架來(lái)作倾鲫。可以在mybatis配置文件配置具體日志實(shí)現(xiàn)萍嬉,我門以log4j2為例:

復(fù)制代碼

配置了mybatis的log實(shí)現(xiàn)以后乌昔,需要引入相對(duì)應(yīng)的日志依賴包。

org.apache.logging.log4jlog4j-api2.11.1org.apache.logging.log4jlog4j-core2.11.1

然后配置日志框架的配置文件(每個(gè)日志框架的配置不同這里以log4j2為例)

<?xml version="1.0"encoding="UTF-8"?>

6. mybatis用到的設(shè)計(jì)模式

mybatis在實(shí)現(xiàn)的時(shí)候用了一些設(shè)計(jì)模式壤追,如:

裝飾器模式:在緩存方面Cache緩存接口的各個(gè)實(shí)現(xiàn)類通過(guò)裝飾器模式來(lái)實(shí)現(xiàn)緩存的功能的疊加

動(dòng)態(tài)代理模式:在映射接口代理和插件方面mybatis使用jdk的動(dòng)態(tài)代理模式是為映射接口提供代理類磕道,為插件系統(tǒng)提供代理生成插件鏈

工廠模式:mybatis為每個(gè)映射接口生成一個(gè)代理工廠MapperProxyFactory,每次獲取映射接口代理是通過(guò)代理工廠獲取

組合模式:SqlNode的各個(gè)子類使用組合模式實(shí)現(xiàn)sql拼接

單例模式:如LogFacotry

模版方法模式:如抽象類BaseExecutor和其子類就是用該模式行冰。模板類定義一個(gè)操作中的算法的骨架溺蕉,而將一些步驟延遲到子類中。使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟悼做。

7. myabtis集成到spring

mybatis集成到spring需要添加mybatis-spring依賴疯特,這個(gè)依賴包是mybatis和spring對(duì)接依賴包。添加spring依賴和mybatis-spring依賴

<!-- spring -->org.springframeworkspring-core5.0.4.RELEASEorg.springframeworkspring-beans5.0.4.RELEASEorg.springframeworkspring-context5.0.4.RELEASEorg.springframeworkspring-jdbc5.0.4.RELEASE<!-- mybatis-spring -->org.mybatismybatis-spring1.3.1

配置spring

<?xml version="1.0"encoding="UTF-8"?>

? ? ? ? http://www.springframework.org/schema/beans/spring-beans.xsd

? ? ? ? http://www.springframework.org/schema/context

? ? ? ? http://www.springframework.org/schema/context/spring-context.xsd"><!-- 屬性掃描 --><!-- 組件掃描 --><!-- 數(shù)據(jù)源 --><!-- 配置sqlSessionFactory工廠bean --><!-- 配置sqlSessionTemplate --><!-- 注冊(cè)掃描映射接口bean -->

從spring配置可以知道m(xù)ybatis-spring主要做了一下幾件事:

配置sqlSessionFactory工廠bean肛走,該bean是一個(gè)工廠bean(可以理解為這個(gè)工廠bean就是SqlSessionFactory的bean漓雅,當(dāng)注入的時(shí)候工廠bean會(huì)自動(dòng)點(diǎn)用getObject方法獲取得到SqlSessionFactory實(shí)例)

配置sqlSessionTemplate會(huì)話模版,它是SqlSession的子類,它相當(dāng)于全局的會(huì)話代理類它內(nèi)部也是通過(guò)代理的方式sql操作委托給別的SqlSession邻吞。因?yàn)樗梢宰鳛槿值腟qlSession所以它是線程安全的组题,之所以線程安全的是因?yàn)樗型ㄟ^(guò)SqlSessionTemplate調(diào)用的諸如selectList、update的方法都會(huì)委托給SqlSessionTemplate內(nèi)部的sqlSessionProxy抱冷,而sqlSessionProxy是一個(gè)SqlSession的代理崔列,其InvocationHandler是SqlSessionInterceptor,在SqlSessionInterceptor.invoke中每次都會(huì)從TransactionSynchronizationManager中獲取SqlSession旺遮,而在TransactionSynchronizationManager中使用ThreadLocal實(shí)現(xiàn)線程安全赵讯。(這里大概描述詳情看源碼SqlSessionTemplate、SqlSessionUtils)

注冊(cè)掃描映射接口bean:MapperScannerConfigurer實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口耿眉,在bean初始化的時(shí)候會(huì)調(diào)用postProcessBeanDefinitionRegistry边翼,MapperScannerConfigurer.postProcessBeanDefinitionRegistry方法內(nèi)就是掃描注冊(cè)映射接口bean的過(guò)程。掃描注冊(cè)映射接口后跷敬,才可以被注入到其他的Component中讯私。

8. mybatis集成springboot自動(dòng)化配置

mybatis集成springboot需要添加一個(gè)start

org.mybatis.spring.bootmybatis-spring-boot-starter1.3.0

其實(shí)mybatis-spring-boot-starter只是個(gè)空的依賴热押,mybatis-spring-boot-starter依賴了mybatis-spring-boot-autoconfigure西傀,主要的代碼在這個(gè)自動(dòng)化配置包里。自動(dòng)化配置依賴會(huì)讀取mybatis相關(guān)的配置屬性桶癣,然后自動(dòng)配置我們上面提到的mybatis相關(guān)的組件拥褂。配置例子:

mybatis.mapper-locations=classpath:/mapper/**/*Mapper.xmlmybatis.typeAliasesPackage=com.test.*.modelmybatis.configuration.map-underscore-to-camel-case=truemybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImplmybatis.configuration.callSettersOnNulls=true

這里不將springboot相關(guān)內(nèi)容,只做配置樣例介紹牙寞。在此我向大家推薦一個(gè)架構(gòu)學(xué)習(xí)交流群饺鹃。交流學(xué)習(xí)群號(hào):938837867 暗號(hào):555 里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:有Spring,MyBatis间雀,Netty源碼分析悔详,高并發(fā)、高性能惹挟、分布式茄螃、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化连锯、分布式架構(gòu)等這些成為架構(gòu)師必備

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末归苍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子运怖,更是在濱河造成了極大的恐慌拼弃,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摇展,死亡現(xiàn)場(chǎng)離奇詭異吻氧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門医男,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)砸狞,“玉大人,你說(shuō)我怎么就攤上這事镀梭〉渡” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵报账,是天一觀的道長(zhǎng)研底。 經(jīng)常有香客問(wèn)我,道長(zhǎng)透罢,這世上最難降的妖魔是什么榜晦? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮羽圃,結(jié)果婚禮上乾胶,老公的妹妹穿的比我還像新娘。我一直安慰自己朽寞,他們只是感情好识窿,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著脑融,像睡著了一般喻频。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肘迎,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天甥温,我揣著相機(jī)與錄音,去河邊找鬼妓布。 笑死姻蚓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的匣沼。 我是一名探鬼主播狰挡,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肛著!你這毒婦竟也來(lái)了圆兵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤枢贿,失蹤者是張志新(化名)和其女友劉穎殉农,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體局荚,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡超凳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年愈污,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轮傍。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡暂雹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出创夜,到底是詐尸還是另有隱情杭跪,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布驰吓,位于F島的核電站涧尿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏檬贰。R本人自食惡果不足惜姑廉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望翁涤。 院中可真熱鬧桥言,春花似錦、人聲如沸葵礼。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)章咧。三九已至倦西,卻和暖如春能真,著一層夾襖步出監(jiān)牢的瞬間赁严,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工粉铐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疼约,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓蝙泼,卻偏偏與公主長(zhǎng)得像程剥,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子汤踏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1 Mybatis入門 1.1 單獨(dú)使用jdbc編程問(wèn)題總結(jié) 1.1.1 jdbc程序 上邊使...
    哇哈哈E閱讀 3,293評(píng)論 0 38
  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis 织鲸? MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,425評(píng)論 0 4
  • MyBatis 理論篇 [TOC] 什么是MyBatis ?MyBatis是支持普通SQL查詢,存儲(chǔ)過(guò)程和高級(jí)映射...
    有_味閱讀 2,881評(píng)論 0 26
  • 夲圣閱讀 241評(píng)論 6 10
  • 白羊座:“你和那個(gè)xx最近好像 接觸挺多 總聽(tīng)你談到她” 潛臺(tái)詞:“ 你沒(méi)理解錯(cuò)溪胶!姐不爽了 而且是相當(dāng)不爽搂擦!” 金...
    隨筆星文閱讀 422評(píng)論 0 2