成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Mybatis中有哪些設(shè)計(jì)模式

Mybatis中有哪些設(shè)計(jì)模式,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。

創(chuàng)新互聯(lián)建站于2013年創(chuàng)立,先為長安等服務(wù)建站,長安等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為長安企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

  1. Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;

  2. 工廠模式,例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;

  3. 單例模式,例如ErrorContext和LogFactory;

  4. 代理模式,Mybatis實(shí)現(xiàn)的核心,比如MapperProxy、ConnectionLogger,用的jdk的動(dòng)態(tài)代理;還有executor.loader包使用了cglib或者javassist達(dá)到延遲加載的效果;

  5. 組合模式,例如SqlNode和各個(gè)子類ChooseSqlNode等;

  6. 模板方法模式,例如BaseExecutor和SimpleExecutor,還有BaseTypeHandler和所有的子類例如IntegerTypeHandler;

  7. 適配器模式,例如Log的Mybatis接口和它對jdbc、log4j等各種日志框架的適配實(shí)現(xiàn);

  8. 裝飾者模式,例如Cache包中的cache.decorators子包中等各個(gè)裝飾者的實(shí)現(xiàn);

  9. 迭代器模式,例如迭代器模式PropertyTokenizer;

接下來挨個(gè)模式進(jìn)行解讀,先介紹模式自身的知識,然后解讀在Mybatis中怎樣應(yīng)用了該模式。

1、Builder模式

Builder模式的定義是“將一個(gè)復(fù)雜對象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示?!?,它屬于創(chuàng)建類模式,一般來說,如果一個(gè)對象的構(gòu)建比較復(fù)雜,超出了構(gòu)造函數(shù)所能包含的范圍,就可以使用工廠模式和Builder模式,相對于工廠模式會(huì)產(chǎn)出一個(gè)完整的產(chǎn)品,Builder應(yīng)用于更加復(fù)雜的對象的構(gòu)建,甚至只會(huì)構(gòu)建產(chǎn)品的一個(gè)部分。

Mybatis中有哪些設(shè)計(jì)模式

在Mybatis環(huán)境的初始化過程中,SqlSessionFactoryBuilder會(huì)調(diào)用XMLConfigBuilder讀取所有的MybatisMapConfig.xml和所有的*Mapper.xml文件,構(gòu)建Mybatis運(yùn)行的核心對象Configuration對象,然后將該Configuration對象作為參數(shù)構(gòu)建一個(gè)SqlSessionFactory對象。

其中XMLConfigBuilder在構(gòu)建Configuration對象時(shí),也會(huì)調(diào)用XMLMapperBuilder用于讀取*Mapper文件,而XMLMapperBuilder會(huì)使用XMLStatementBuilder來讀取和build所有的SQL語句。

在這個(gè)過程中,有一個(gè)相似的特點(diǎn),就是這些Builder會(huì)讀取文件或者配置,然后做大量的XpathParser解析、配置或語法的解析、反射生成對象、存入結(jié)果緩存等步驟,這么多的工作都不是一個(gè)構(gòu)造函數(shù)所能包括的,因此大量采用了Builder模式來解決。

對于builder的具體類,方法都大都用build*開頭,比如SqlSessionFactoryBuilder為例,它包含以下方法:

Mybatis中有哪些設(shè)計(jì)模式

SqlSession可以認(rèn)為是一個(gè)Mybatis工作的核心的接口,通過這個(gè)接口可以執(zhí)行執(zhí)行SQL語句、獲取Mappers、管理事務(wù)。類似于連接MySQL的Connection對象。

可以看到,該Factory的openSession方法重載了很多個(gè),分別支持autoCommit、Executor、Transaction等參數(shù)的輸入,來構(gòu)建核心的SqlSession對象。

在DefaultSqlSessionFactory的默認(rèn)工廠實(shí)現(xiàn)里,有一個(gè)方法可以看出工廠怎么產(chǎn)出一個(gè)產(chǎn)品:

 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level,
   boolean autoCommit) {
  Transaction tx = null;
  try {
   final Environment environment = configuration.getEnvironment();
   final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
   tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
   final Executor executor = configuration.newExecutor(tx, execType);
   return new DefaultSqlSession(configuration, executor, autoCommit);
  } catch (Exception e) {
   closeTransaction(tx); // may have fetched a connection so lets call
         // close()
   throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
  } finally {
   ErrorContext.instance().reset();
  }
 }

這是一個(gè)openSession調(diào)用的底層方法,該方法先從configuration讀取對應(yīng)的環(huán)境配置,然后初始化TransactionFactory獲得一個(gè)Transaction對象,然后通過Transaction獲取一個(gè)Executor對象,最后通過configuration、Executor、是否autoCommit三個(gè)參數(shù)構(gòu)建了SqlSession。

在這里其實(shí)也可以看到端倪,SqlSession的執(zhí)行,其實(shí)是委托給對應(yīng)的Executor來進(jìn)行的。

而對于LogFactory,它的實(shí)現(xiàn)代碼:

public final class LogFactory {
 private static Constructor<? extends Log> logConstructor;

 private LogFactory() {
  // disable construction
 }

 public static Log getLog(Class<?> aClass) {
  return getLog(aClass.getName());
 }

這里有個(gè)特別的地方,是Log變量的的類型是Constructor<? extends Log>,也就是說該工廠生產(chǎn)的不只是一個(gè)產(chǎn)品,而是具有Log公共接口的一系列產(chǎn)品,比如Log4jImpl、Slf4jImpl等很多具體的Log。

3、單例模式

單例模式(Singleton Pattern):單例模式確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例,這個(gè)類稱為單例類,它提供全局訪問的方法。

單例模式的要點(diǎn)有三個(gè):一是某個(gè)類只能有一個(gè)實(shí)例;二是它必須自行創(chuàng)建這個(gè)實(shí)例;三是它必須自行向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。單例模式是一種對象創(chuàng)建型模式。單例模式又名單件模式或單態(tài)模式。

Mybatis中有哪些設(shè)計(jì)模式

在Mybatis中有兩個(gè)地方用到單例模式,ErrorContext和LogFactory,其中ErrorContext是用在每個(gè)線程范圍內(nèi)的單例,用于記錄該線程的執(zhí)行環(huán)境錯(cuò)誤信息,而LogFactory則是提供給整個(gè)Mybatis使用的日志工廠,用于獲得針對項(xiàng)目配置好的日志對象。

ErrorContext的單例實(shí)現(xiàn)代碼:

public class ErrorContext {

 private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<ErrorContext>();

 private ErrorContext() {
 }

 public static ErrorContext instance() {
  ErrorContext context = LOCAL.get();
  if (context == null) {
   context = new ErrorContext();
   LOCAL.set(context);
  }
  return context;
 }

構(gòu)造函數(shù)是private修飾,具有一個(gè)static的局部instance變量和一個(gè)獲取instance變量的方法,在獲取實(shí)例的方法中,先判斷是否為空如果是的話就先創(chuàng)建,然后返回構(gòu)造好的對象。

只是這里有個(gè)有趣的地方是,LOCAL的靜態(tài)實(shí)例變量使用了ThreadLocal修飾,也就是說它屬于每個(gè)線程各自的數(shù)據(jù),而在instance()方法中,先獲取本線程的該實(shí)例,如果沒有就創(chuàng)建該線程獨(dú)有的ErrorContext。

4、代理模式

代理模式可以認(rèn)為是Mybatis的核心使用的模式,正是由于這個(gè)模式,我們只需要編寫Mapper.java接口,不需要實(shí)現(xiàn),由Mybatis后臺幫我們完成具體SQL的執(zhí)行。

代理模式(Proxy Pattern) :給某一個(gè)對象提供一個(gè)代 理,并由代理對象控制對原對象的引用。代理模式的英 文叫做Proxy或Surrogate,它是一種對象結(jié)構(gòu)型模式。

代理模式包含如下角色:

  • Subject: 抽象主題角色

  • Proxy: 代理主題角色

  • RealSubject: 真實(shí)主題角色

Mybatis中有哪些設(shè)計(jì)模式

這里有兩個(gè)步驟,第一個(gè)是提前創(chuàng)建一個(gè)Proxy,第二個(gè)是使用的時(shí)候會(huì)自動(dòng)請求Proxy,然后由Proxy來執(zhí)行具體事務(wù);

當(dāng)我們使用Configuration的getMapper方法時(shí),會(huì)調(diào)用mapperRegistry.getMapper方法,而該方法又會(huì)調(diào)用mapperProxyFactory.newInstance(sqlSession)來生成一個(gè)具體的代理:

public class MapperProxyFactory<T> {

 private final Class<T> mapperInterface;
 private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();

 public MapperProxyFactory(Class<T> mapperInterface) {
  this.mapperInterface = mapperInterface;
 }

 public Class<T> getMapperInterface() {
  return mapperInterface;
 }

 public Map<Method, MapperMethod> getMethodCache() {
  return methodCache;
 }

 @SuppressWarnings("unchecked")
 protected T newInstance(MapperProxy<T> mapperProxy) {
  return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface },
    mapperProxy);
 }

 public T newInstance(SqlSession sqlSession) {
  final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
  return newInstance(mapperProxy);
 }

}

在這里,先通過T newInstance(SqlSession sqlSession)方法會(huì)得到一個(gè)MapperProxy對象,然后調(diào)用T newInstance(MapperProxymapperProxy)生成代理對象然后返回。

而查看MapperProxy的代碼,可以看到如下內(nèi)容:

public class MapperProxy<T> implements InvocationHandler, Serializable {

 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  try {
   if (Object.class.equals(method.getDeclaringClass())) {
    return method.invoke(this, args);
   } else if (isDefaultMethod(method)) {
    return invokeDefaultMethod(proxy, method, args);
   }
  } catch (Throwable t) {
   throw ExceptionUtil.unwrapThrowable(t);
  }
  final MapperMethod mapperMethod = cachedMapperMethod(method);
  return mapperMethod.execute(sqlSession, args);
 }

非常典型的,該MapperProxy類實(shí)現(xiàn)了InvocationHandler接口,并且實(shí)現(xiàn)了該接口的invoke方法。

通過這種方式,我們只需要編寫Mapper.java接口類,當(dāng)真正執(zhí)行一個(gè)Mapper接口的時(shí)候,就會(huì)轉(zhuǎn)發(fā)給MapperProxy.invoke方法,而該方法則會(huì)調(diào)用后續(xù)的sqlSession.cud>executor.execute>prepareStatement等一系列方法,完成SQL的執(zhí)行和返回。

5、組合模式

組合模式組合多個(gè)對象形成樹形結(jié)構(gòu)以表示“整體-部分”的結(jié)構(gòu)層次。

組合模式對單個(gè)對象(葉子對象)和組合對象(組合對象)具有一致性,它將對象組織到樹結(jié)構(gòu)中,可以用來描述整體與部分的關(guān)系。同時(shí)它也模糊了簡單元素(葉子對象)和復(fù)雜元素(容器對象)的概念,使得客戶能夠像處理簡單元素一樣來處理復(fù)雜元素,從而使客戶程序能夠與復(fù)雜元素的內(nèi)部結(jié)構(gòu)解耦。

在使用組合模式中需要注意一點(diǎn)也是組合模式最關(guān)鍵的地方:葉子對象和組合對象實(shí)現(xiàn)相同的接口。這就是組合模式能夠?qū)⑷~子節(jié)點(diǎn)和對象節(jié)點(diǎn)進(jìn)行一致處理的原因。

Mybatis支持動(dòng)態(tài)SQL的強(qiáng)大功能,比如下面的這個(gè)SQL:

<update id="update" parameterType="org.format.dynamicproxy.mybatis.bean.User">
    UPDATE users
    <trim prefix="SET" prefixOverrides=",">
        <if test="name != null and name != ''">
            name = #{name}
        </if>
        <if test="age != null and age != ''">
            , age = #{age}
        </if>
        <if test="birthday != null and birthday != ''">
            , birthday = #{birthday}
        </if>
    </trim>
    where id = ${id}
</update>

在這里面使用到了trim、if等動(dòng)態(tài)元素,可以根據(jù)條件來生成不同情況下的SQL;

在DynamicSqlSource.getBoundSql方法里,調(diào)用了rootSqlNode.apply(context)方法,apply方法是所有的動(dòng)態(tài)節(jié)點(diǎn)都實(shí)現(xiàn)的接口:

public interface SqlNode {
 boolean apply(DynamicContext context);
}

對于實(shí)現(xiàn)該SqlSource接口的所有節(jié)點(diǎn),就是整個(gè)組合模式樹的各個(gè)節(jié)點(diǎn):

Mybatis中有哪些設(shè)計(jì)模式

組合模式的簡單之處在于,所有的子節(jié)點(diǎn)都是同一類節(jié)點(diǎn),可以遞歸的向下執(zhí)行,比如對于TextSqlNode,因?yàn)樗亲畹讓拥娜~子節(jié)點(diǎn),所以直接將對應(yīng)的內(nèi)容append到SQL語句中:

 @Override
 public boolean apply(DynamicContext context) {
  GenericTokenParser parser = createParser(new BindingTokenParser(context, injectionFilter));
  context.appendSql(parser.parse(text));
  return true;
 }

但是對于IfSqlNode,就需要先做判斷,如果判斷通過,仍然會(huì)調(diào)用子元素的SqlNode,即contents.apply方法,實(shí)現(xiàn)遞歸的解析。

 @Override
 public boolean apply(DynamicContext context) {
  if (evaluator.evaluateBoolean(test, context.getBindings())) {
   contents.apply(context);
   return true;
  }
  return false;
 }

6、模板方法模式

模板方法模式是所有模式中最為常見的幾個(gè)模式之一,是基于繼承的代碼復(fù)用的基本技術(shù)。

模板方法模式需要開發(fā)抽象類和具體子類的設(shè)計(jì)師之間的協(xié)作。一個(gè)設(shè)計(jì)師負(fù)責(zé)給出一個(gè)算法的輪廓和骨架,另一些設(shè)計(jì)師則負(fù)責(zé)給出這個(gè)算法的各個(gè)邏輯步驟。代表這些具體邏輯步驟的方法稱做基本方法(primitive method);而將這些基本方法匯總起來的方法叫做模板方法(template method),這個(gè)設(shè)計(jì)模式的名字就是從此而來。

模板類定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。

Mybatis中有哪些設(shè)計(jì)模式

其中的BaseExecutor就采用了模板方法模式,它實(shí)現(xiàn)了大部分的SQL執(zhí)行邏輯,然后把以下幾個(gè)方法交給子類定制化完成:

 protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;

 protected abstract List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException;

 protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds,
   ResultHandler resultHandler, BoundSql boundSql) throws SQLException;

該模板方法類有幾個(gè)子類的具體實(shí)現(xiàn),使用了不同的策略:

  • 簡單SimpleExecutor:每執(zhí)行一次update或select,就開啟一個(gè)Statement對象,用完立刻關(guān)閉Statement對象。(可以是Statement或PrepareStatement對象)

  • 重用ReuseExecutor:執(zhí)行update或select,以sql作為key查找Statement對象,存在就使用,不存在就創(chuàng)建,用完后,不關(guān)閉Statement對象,而是放置于Map<String, Statement>內(nèi),供下一次使用。(可以是Statement或PrepareStatement對象)

  • 批量BatchExecutor:執(zhí)行update(沒有select,JDBC批處理不支持select),將所有sql都添加到批處理中(addBatch()),等待統(tǒng)一執(zhí)行(executeBatch()),它緩存了多個(gè)Statement對象,每個(gè)Statement對象都是addBatch()完畢后,等待逐一執(zhí)行executeBatch()批處理的;BatchExecutor相當(dāng)于維護(hù)了多個(gè)桶,每個(gè)桶里都裝了很多屬于自己的SQL,就像蘋果藍(lán)里裝了很多蘋果,番茄藍(lán)里裝了很多番茄,最后,再統(tǒng)一倒進(jìn)倉庫。(可以是Statement或PrepareStatement對象)

比如在SimpleExecutor中這樣實(shí)現(xiàn)update方法:

 @Override
 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
  Statement stmt = null;
  try {
   Configuration configuration = ms.getConfiguration();
   StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null,
     null);
   stmt = prepareStatement(handler, ms.getStatementLog());
   return handler.update(stmt);
  } finally {
   closeStatement(stmt);
  }
 }

7、適配器模式

適配器模式(Adapter Pattern) :將一個(gè)接口轉(zhuǎn)換成客戶希望的另一個(gè)接口,適配器模式使接口不兼容的那些類可以一起工作,其別名為包裝器(Wrapper)。適配器模式既可以作為類結(jié)構(gòu)型模式,也可以作為對象結(jié)構(gòu)型模式。

在Mybatsi的logging包中,有一個(gè)Log接口:

public interface Log {

 boolean isDebugEnabled();

 boolean isTraceEnabled();

 void error(String s, Throwable e);

 void error(String s);

 void debug(String s);

 void trace(String s);

 void warn(String s);

}

該接口定義了Mybatis直接使用的日志方法,而Log接口具體由誰來實(shí)現(xiàn)呢?Mybatis提供了多種日志框架的實(shí)現(xiàn),這些實(shí)現(xiàn)都匹配這個(gè)Log接口所定義的接口方法,最終實(shí)現(xiàn)了所有外部日志框架到Mybatis日志包的適配:

Mybatis中有哪些設(shè)計(jì)模式

比如對于Log4jImpl的實(shí)現(xiàn)來說,該實(shí)現(xiàn)持有了org.apache.log4j.Logger的實(shí)例,然后所有的日志方法,均委托該實(shí)例來實(shí)現(xiàn)。

public class Log4jImpl implements Log {

 private static final String FQCN = Log4jImpl.class.getName();

 private Logger log;

 public Log4jImpl(String clazz) {
  log = Logger.getLogger(clazz);
 }

 @Override
 public boolean isDebugEnabled() {
  return log.isDebugEnabled();
 }

 @Override
 public boolean isTraceEnabled() {
  return log.isTraceEnabled();
 }

 @Override
 public void error(String s, Throwable e) {
  log.log(FQCN, Level.ERROR, s, e);
 }

 @Override
 public void error(String s) {
  log.log(FQCN, Level.ERROR, s, null);
 }

 @Override
 public void debug(String s) {
  log.log(FQCN, Level.DEBUG, s, null);
 }

 @Override
 public void trace(String s) {
  log.log(FQCN, Level.TRACE, s, null);
 }

 @Override
 public void warn(String s) {
  log.log(FQCN, Level.WARN, s, null);
 }

}

8、裝飾者模式

裝飾模式(Decorator Pattern) :動(dòng)態(tài)地給一個(gè)對象增加一些額外的職責(zé)(Responsibility),就增加對象功能來說,裝飾模式比生成子類實(shí)現(xiàn)更為靈活。其別名也可以稱為包裝器(Wrapper),與適配器模式的別名相同,但它們適用于不同的場合。根據(jù)翻譯的不同,裝飾模式也有人稱之為“油漆工模式”,它是一種對象結(jié)構(gòu)型模式。

Mybatis中有哪些設(shè)計(jì)模式

用于裝飾PerpetualCache的標(biāo)準(zhǔn)裝飾器共有8個(gè)(全部在org.apache.ibatis.cache.decorators包中):

  1. FifoCache:先進(jìn)先出算法,緩存回收策略

  2. LoggingCache:輸出緩存命中的日志信息

  3. LruCache:最近最少使用算法,緩存回收策略

  4. ScheduledCache:調(diào)度緩存,負(fù)責(zé)定時(shí)清空緩存

  5. SerializedCache:緩存序列化和反序列化存儲(chǔ)

  6. SoftCache:基于軟引用實(shí)現(xiàn)的緩存管理策略

  7. SynchronizedCache:同步的緩存裝飾器,用于防止多線程并發(fā)訪問

  8. WeakCache:基于弱引用實(shí)現(xiàn)的緩存管理策略

另外,還有一個(gè)特殊的裝飾器TransactionalCache:事務(wù)性的緩存

正如大多數(shù)持久層框架一樣,mybatis緩存同樣分為一級緩存和二級緩存

  • 一級緩存,又叫本地緩存,是PerpetualCache類型的永久緩存,保存在執(zhí)行器中(BaseExecutor),而執(zhí)行器又在SqlSession(DefaultSqlSession)中,所以一級緩存的生命周期與SqlSession是相同的。

  • 二級緩存,又叫自定義緩存,實(shí)現(xiàn)了Cache接口的類都可以作為二級緩存,所以可配置如encache等的第三方緩存。二級緩存以namespace名稱空間為其唯一標(biāo)識,被保存在Configuration核心配置對象中。

二級緩存對象的默認(rèn)類型為PerpetualCache,如果配置的緩存是默認(rèn)類型,則mybatis會(huì)根據(jù)配置自動(dòng)追加一系列裝飾器。

Cache對象之間的引用順序?yàn)椋?/p>

SynchronizedCache–>LoggingCache–>SerializedCache–>ScheduledCache–>LruCache–>PerpetualCache

9、迭代器模式

迭代器(Iterator)模式,又叫做游標(biāo)(Cursor)模式。GOF給出的定義為:提供一種方法訪問一個(gè)容器(container)對象中各個(gè)元素,而又不需暴露該對象的內(nèi)部細(xì)節(jié)。

Mybatis中有哪些設(shè)計(jì)模式

比如Mybatis的PropertyTokenizer是property包中的重量級類,該類會(huì)被reflection包中其他的類頻繁的引用到。這個(gè)類實(shí)現(xiàn)了Iterator接口,在使用時(shí)經(jīng)常被用到的是Iterator接口中的hasNext這個(gè)函數(shù)。

public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
 private String name;
 private String indexedName;
 private String index;
 private String children;

 public PropertyTokenizer(String fullname) {
  int delim = fullname.indexOf('.');
  if (delim > -1) {
   name = fullname.substring(0, delim);
   children = fullname.substring(delim + 1);
  } else {
   name = fullname;
   children = null;
  }
  indexedName = name;
  delim = name.indexOf('[');
  if (delim > -1) {
   index = name.substring(delim + 1, name.length() - 1);
   name = name.substring(0, delim);
  }
 }

 public String getName() {
  return name;
 }

 public String getIndex() {
  return index;
 }

 public String getIndexedName() {
  return indexedName;
 }

 public String getChildren() {
  return children;
 }

 @Override
 public boolean hasNext() {
  return children != null;
 }

 @Override
 public PropertyTokenizer next() {
  return new PropertyTokenizer(children);
 }

 @Override
 public void remove() {
  throw new UnsupportedOperationException(
    "Remove is not supported, as it has no meaning in the context of properties.");
 }
}

看完上述內(nèi)容,你們掌握Mybatis中有哪些設(shè)計(jì)模式的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

網(wǎng)站欄目:Mybatis中有哪些設(shè)計(jì)模式
網(wǎng)站鏈接:http://jinyejixie.com/article42/jopdec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣、自適應(yīng)網(wǎng)站、手機(jī)網(wǎng)站建設(shè)、軟件開發(fā)、品牌網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)
桑日县| 塔城市| 淅川县| 多伦县| 蒙山县| 墨竹工卡县| 平陆县| 乌兰县| 京山县| 闸北区| 屯留县| 弥渡县| 鄂伦春自治旗| 诏安县| 阜康市| 连州市| 英超| 湖北省| 沙湾县| 邢台县| 肥城市| 仲巴县| 德令哈市| 界首市| 漳浦县| 商城县| 璧山县| 巴青县| 布拖县| 萨嘎县| 靖西县| 昂仁县| 林州市| 依安县| 兴城市| 博野县| 南川市| 阜宁县| 岐山县| 东海县| 马尔康县|