设计模式之Mybaits之工厂模式

简介: 设计模式之Mybaits之工厂模式

一、趣说工厂模式

工厂模式是Java中最常用的设计模式之一。

工厂模式就是提供一个工厂类,当有客户端需要调用的时候,只调用这个工厂类就可以得到自己想要的结果,从而无需关注某类的具体实现过程。

就好比,你是个富二代,你可以饭来张口衣来伸手;你只负责拿钱去买买买,而不用关心你买的东西是怎么做的,也不必关心钱是谁赚的,从哪里来了。

二、Mybatis中如何运用的

在Mybatis中运用工厂模式最典型的就是SqlSessionFactory。

SqlSession是Mybatis中最最最核心的一个模块了。

可以简单的理解,Mybatis中所有的sql都是通过SqlSession来最终执行的。

可以执行jdbc的操作(增删改查)。

SqlSessionFactory就是构建SqlSession对象的一个工厂类

工厂模式用一句话来说就是用来帮你创建对象的。

SqlSessionFactory中有一个openSession(…)方法。

如下所示:

public interface SqlSessionFactory {
  SqlSession openSession();
  SqlSession openSession(boolean autoCommit);
  SqlSession openSession(Connection connection);
  SqlSession openSession(TransactionIsolationLevel level);
  SqlSession openSession(ExecutorType execType);
  SqlSession openSession(ExecutorType execType, boolean autoCommit);
  SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
  SqlSession openSession(ExecutorType execType, Connection connection);
  Configuration getConfiguration();

可以看到有很多种创建SqlSession的方式。

其中SqlSession openSession(ExecutorType execType);就是一个很典型的应用了工厂模式来达到目的的。

点进去这个SqlSession openSession(ExecutorType execType);到DefaultSqlSessionFactory类中,我们发现又调用了一个:

@Override
  public SqlSession openSession(ExecutorType execType) {
    return openSessionFromDataSource(execType, null, false);
  }

继续点进去:

可以看到,真的是见名之意了。功能就是打开会话的

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);
      //Executor:SQL语句的执行器
      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();
    }
  }

其中我们要讲的最核心的就是:“创建SQL语句的执行器”

//Executor:SQL语句的执行器
final Executor executor = configuration.newExecutor(tx, execType);

代码如下:

可以看到,在创建Executor对象的时候,是根据不同的类型,创建不同的对象的。

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

三、我在项目中真实运用工厂模式的案例

我在使用ES的时候,就运用了工厂模式。

ES支持模糊匹配和精确匹配。

如果没接触过ES的话,可以把模糊匹配想象成是sql的like,可以把精确匹配想象成sql中的=号。

在项目中的需求是:

返回匹配数据结果的前100条数据。

返回的数据 <= 100

旧的实现步骤:

1、一步到位,直接模糊匹配,然后返回前100条。

不足之处:例如:我搜索一个“食堂相关制度未在食堂公示”。

ES会进行切词,可能会切成:“食堂”,“相关制度”,“未在食堂公示”。

那么就会匹配这三个短语,从而返回这三个中的数据,最终的前100条数据中,并没有把“食堂相关制度未在食堂公示”这条数据显示在第一个位置。

这样用户的体验就会很不好了。

解决的办法:

最终目的:返回100条数据。

1、先进行精确匹配;

2、如果精确匹配到了说明这些数据肯定要展示在前面的;例如:此时已经匹配了10条数据。

3、然后对这10条数据进行排序,谁的长度最小,谁在前面。(进一步提高了准确度)

4、再进行模糊匹配;

5、此时应该拿的数据是100-10=90条。

6、返回90+10=100条数据。

此时的重点是:

在写代码的时候,我们要创建两套代码,这两套代码的相似度在99%,只有一个调用的方法变了,其余的参数都没变,显得很冗余。

旧:

//模糊构造模糊查询的SearchSourceBuilder对象
private SearchSourceBuilder builderMatchQuery(参数......) {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        QueryBuilder queryBuilder = null;
      .....此处省略N行代码
        //核心代码就是这一句, QueryBuilders.matchQuery返回的QueryBuilder对象就是一个可以构造一个模糊查询的条件
        queryBuilder = QueryBuilders.matchQuery(searchType,content);
      .....此处省略N行代码
        return searchSourceBuilder;
}
//构造精确查询的SearchSourceBuilder对象
private SearchSourceBuilder builderMatchPhraseQuery(参数......) {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        QueryBuilder queryBuilder = null;
        ......
        //精确查询 QueryBuilders.matchPhraseQuery返回的QueryBuilder,就是用来构建精确查询的条件
        queryBuilder = QueryBuilders.matchPhraseQuery(searchType,content);
    .......
        return searchSourceBuilder;
}

我们可以看到两句核心的语句是:

QueryBuilders.matchPhraseQuery和QueryBuilders.matchQuery都可以返回QueryBuilder对象。那么可不可以简单一些呢?

QueryBuilder queryBuilder = null;
//QueryBuilders.matchPhraseQuery返回的QueryBuilder,就是用来构建精确查询的条件
queryBuilder = QueryBuilders.matchPhraseQuery(searchType,content);
// QueryBuilders.matchQuery返回的QueryBuilder对象就是一个可以构造一个模糊查询的条件
queryBuilder = QueryBuilders.matchQuery(searchType,content);

答案是可以的,利用工厂模式就可以很好的解决。

运用工厂模式:

可以看到下面这段代码就可以把上面的代码减少了50%的量。

我根据传递的buildQueryType参数,决定返回的QueryBuilder对象是哪个。

//模糊构造模糊查询的SearchSourceBuilder对象
private SearchSourceBuilder builderMatchQueryAndMatchPhraseQuery(其他参数......,Type buildQueryType) {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        QueryBuilder queryBuilder = null;
    .....此处省略N行代码
        //模糊查询
        if(buildQueryType==Type.BOOLEAN){
            queryBuilder = QueryBuilders.matchQuery(searchType,content);
        //精确查询
        }else if(buildQueryType==Type.PHRASE){
            queryBuilder = QueryBuilders.matchPhraseQuery(searchType,content);
        }
      .....此处省略N行代码
        return searchSourceBuilder;
}

我写的上面这个代码,并不是真正的模仿工厂模式来写的,而且运用了工厂模式的思想。

简单吧。

目录
相关文章
|
JSON 前端开发 Java
【十八】springboot实现自定义全局异常处理
【十八】springboot实现自定义全局异常处理
564 2
【十八】springboot实现自定义全局异常处理
|
SQL 数据可视化 关系型数据库
DataX教程(05)- DataX Web项目实践
DataX教程(05)- DataX Web项目实践
5168 0
DataX教程(05)- DataX Web项目实践
|
11月前
|
数据可视化 安全 持续交付
敏捷方法大比拼:Scrum 适合你,还是 Kanban 更合适?
在数字化时代,企业面临项目管理的诸多挑战,如信息不透明、沟通低效等。Scrum 和 Kanban 作为敏捷管理方法,通过迭代优化和流程可视化提升协作效率与交付速度。Scrum 适合周期性迭代交付,强调短周期冲刺;Kanban 则适用于持续交付,强调任务流动性和灵活性。两者结合可形成 ScrumBan 模式,进一步优化任务处理。 对于数据安全要求高的企业,私有化部署工具(如板栗看板)确保数据自主可控、高安全性及定制化需求,保障业务连续性。选择合适的敏捷方法并结合私有化部署,能有效提升团队协作效率,助力企业在竞争中保持领先。
|
Java Maven
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
在Java项目中,启动jar包时遇到“no main manifest attribute”错误,且打包大小明显偏小。常见原因包括:1) Maven配置中跳过主程序打包;2) 缺少Manifest文件或Main-Class属性。解决方案如下:
2849 8
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
|
机器学习/深度学习 监控 算法
Keras进阶:模型调优与部署
该文介绍了Keras模型调优与部署的策略。调优包括调整网络结构(增减层数、改变层类型、使用正则化)、优化算法与参数(选择优化器、学习率衰减)、数据增强(图像变换、噪声添加)、模型集成(Bagging、Boosting)和超参数搜索(网格搜索、随机搜索、贝叶斯优化)。部署涉及模型保存加载、压缩(剪枝、量化、蒸馏)、转换(TensorFlow Lite、ONNX)和服务化(TensorFlow Serving、Docker)。文章强调了持续监控与更新的重要性,以适应不断变化的数据和需求。【6月更文挑战第7天】
503 8
|
负载均衡 Java 开发者
如何在Spring Boot项目中实现微服务架构?
如何在Spring Boot项目中实现微服务架构?
1121 1
|
SQL 存储 druid
浅析SaaS多租户系统数据隔离实现方案
多租户问题,其是一种架构设计方式,就是在一台或者一组服务器上运行的SaaS系统,可以为多个租户(客户)提供服务,目的是为了让多个租户在互联网环境下使用同一套程序,且保证租户间的数据隔离。从这种架构设计的模式上,不难看出来,多租户架构的重点就是同一套程序下多个租户数据的隔离。由于租户数据是集中存储的,所以要实现数据的安全性,就是看能否实现对租户数据的隔离,防止租户数据不经意或被他人恶意地获取和篡改
2557 0
|
数据安全/隐私保护
kali下设置root权限(包含很多技巧)
kali下设置root权限(包含很多技巧)
|
安全 Java 数据库
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
这篇文章是关于Apache Shiro权限管理框架的详细学习指南,涵盖了Shiro的基本概念、认证与授权流程,并通过Spring Boot测试模块演示了Shiro在单应用环境下的使用,包括与IniRealm、JdbcRealm的集成以及自定义Realm的实现。
391 3
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
|
关系型数据库 MySQL 数据库
Windows 安装 MySQL 5.7 x64 位
Windows 安装 MySQL 5.7 x64 位
1459 0

热门文章

最新文章