使用jOOQ的MockDataProvider破解简单的JDBC ResultSet缓存

某些查询不应该一直访问数据库。 例如,当您查询主数据 (例如系统设置,语言,翻译等)时,您可能希望避免一直通过网络发送相同的愚蠢查询(和结果)。 例如:

SELECT * FROM languages

大多数数据库都维护缓冲区高速缓存以加快这些查询的速度,因此您不必总是打磁盘。 一些数据库为每个游标维护结果集缓存,或者它们的JDBC驱动程序甚至可能直接在驱动程序中实现结果集缓存-例如,Oracle中的一项鲜为人知的功能 :

SELECT /*+ RESULT_CACHE */ * FROM languages

但是您可能没有使用Oracle, 并且由于修补JDBC很麻烦 ,因此您可能不得不在数据访问或服务层上一层或两层实施高速缓存:

class LanguageService {private Cache cache;List<Language> getLanguages() {List<Language> result = cache.get();if (result == null) {result = doGetLanguages();cache.put(result);}return result;}
}

而是在JDBC层中进行

尽管这在每个服务和方法级别上都可以正常工作,但是当您仅查询那些结果的一部分时,它可能很快就会变得乏味。 例如,当您添加其他过滤器时会怎样? 您是否也应该缓存该查询? 您应该在缓存上执行过滤器,还是每个过滤器至少访问数据库一次?

class LanguageService {private Cache cache;List<Language> getLanguages() { ... }List<Language> getLanguages(Country country) {// Another cache?// Query the cache only and delegate to//     getLanguages()?// Or don't cache this at all?}
}

如果我们有以下形式的缓存,那会不会很好:

Map<String, ResultSet> cache;

…缓存可重复使用的JDBC ResultSets (或更优:jOOQ Results ),并在每次遇到相同的查询字符串时返回相同的结果。

为此使用jOOQ的MockDataProvider

jOOQ附带了一个MockConnection ,它为您实现了JDBC Connection API, MockConnection了所有其他对象,例如PreparedStatementResultSet等。我们已经在上一篇博客文章中介绍了此有用的工具,用于单元测试 。

但是您也可以“模拟”您的连接以实现缓存! 考虑以下非常简单的MockDataProvider

class ResultCache implements MockDataProvider {final Map<String, Result<?>> cache = new ConcurrentHashMap<>();final Connection connection;ResultCache(Connection connection) {this.connection = connection;}@Overridepublic MockResult[] execute(MockExecuteContext ctx)throws SQLException {Result<?> result;// Add more sophisticated caching criteriaif (ctx.sql().contains("from language")) {// We're using this very useful new Java 8// API for atomic cache value calculationresult = cache.computeIfAbsent(ctx.sql(),sql -> DSL.using(connection).fetch(ctx.sql(),ctx.bindings()));}// All other queries go to the databaseelse {result = DSL.using(connection).fetch(ctx.sql(), ctx.bindings());}return new MockResult[] { new MockResult(result.size(), result)};}
}

显然,这是一个非常简单的示例。 真正的缓存将涉及无效性(基于时间,基于更新等)以及更多的选择性缓存条件,而不仅仅是from language匹配。

但是事实是,使用上述ResultCache ,我们现在可以包装所有JDBC连接,并防止对从语言表中查询的所有查询多次访问数据库! 使用jOOQ API的示例:

DSLContext normal = DSL.using(connection);
DSLContext cached = DSL.using(new MockConnection(new ResultCache(connection))
);// This executs a select count(*) from language query
assertEquals(4, cached.fetchCount(LANGUAGE));
assertEquals(4, normal.fetchCount(LANGUAGE));// Let's add another language (using normal config):
LanguageRecord lang = normal.newRecord(LANGUAGE);
lang.setName("German");
lang.store();// Checking again on the language table:
assertEquals(4, cached.fetchCount(LANGUAGE));
assertEquals(5, normal.fetchCount(LANGUAGE));

缓存就像一个魅力! 请注意,当前的缓存实现仅基于SQL字符串(应该如此)。 如果仅对SQL字符串进行少量修改,就会遇到另一个高速缓存未命中的情况,查询将返回数据库:

// This query is not the same as the cached one, it
// fetches two count(*) expressions. Thus we go back
// to the database and get the latest result.
assertEquals(5, (int) cached.select(count(),count()).from(LANGUAGE).fetchOne().value1());// This still has the "stale" previous result
assertEquals(4, cached.fetchCount(LANGUAGE));

结论

缓存很难。 很难。 除了并发,命名和一处错误外,它还是软件中最困难的三个问题之一。

本文不建议在JDBC级别实现缓存。 您可能会自己决定,也可能不会。 但是,当您这样做时,就可以看到使用jOOQ实现这种缓存有多么容易。

最好的是,您不必在所有应用程序中都使用jOOQ。 您可以将其仅用于此特定用例(以及用于模拟JDBC ),并继续使用JDBC,MyBatis,Hibernate等,只要使用jOOQ MockConnection修补其他框架的JDBC连接即可。

翻译自: https://www.javacodegeeks.com/2015/03/hack-up-a-simple-jdbc-resultset-cache-using-jooqs-mockdataprovider.html

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

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

相关文章

ASP.NET内置对象

Request[从浏览器获取信息] QueryString:获取HTTP查询字符串变量集合 Path:获取当前请求的虚拟路径 UserHostAddress:获取远程客户端的IP主机地址 Browser:获取有关正在请求的客户端浏览器功能的信息 Form:获取窗体变量的集合 Url:获取当前请求的URL信息 MapPath():返回与Web服…

java爬虫新闻网站_java爬虫 之 搜狐新闻爬虫(一)

最近开始学习java爬虫&#xff0c;网上很多教程&#xff0c;自己找的时候花了好久的时间去理解别人的思路。打算将自己最近的学习进度稍作整理&#xff0c;理清思路。主要工具使用jsoup&#xff1a;具体用法看http://blog.csdn.net/u012315428/article/details/51135640下面是获…

easyui源码翻译1.32--ValidateBox(验证框)

前言 使用$.fn.validatebox.defaults重写默认值对象。下载该插件翻译源码 validatebox(验证框)的设计目的是为了验证输入的表单字段是否有效。如果用户输入了无效的值&#xff0c;它将会更改输入框的背景颜色&#xff0c;并且显示警告图标和提示信息。该验证框可以结合form(表单…

java静态方法获取对象_JavaPowerMockito模拟单个静态方法和返回对象

小编典典你想要做的是1的一部分和2的全部的组合。你需要使用PowerMockito.mockStatic为类的所有静态方法启用静态模拟。这意味着可以使用when-thenReturn语法对它们进行存根。但是&#xff0c;当你调用尚未在模拟实例上显式存根的方法时&#xff0c;你正在使用的2个参数的mathS…

从战中反弹:将Git提交信息作为JSON返回

在某些情况下&#xff0c;我们必须知道部署到远程服务器的Web应用程序的确切版本。 例如&#xff0c;客户可能想知道我们是否已经在服务器X上部署了错误修复程序。 当然&#xff0c;我们可以尝试使用“传统”方法找到该问题的答案。 问题是&#xff1a; 没有人不记得是谁更新…

在论坛中出现的各种疑难问题:日志收缩问题

最近&#xff0c;在论坛中&#xff0c;遇到了不少疑难的问题&#xff0c;在此特别记录&#xff0c;同时也感谢发帖人的分享、以及其他网友的热心回答。 1、日志暴大&#xff0c;无法收缩&#xff0c;谁来挑战一下&#xff01; http://bbs.csdn.net/topics/390674731?page1#pos…

学java前要学css_教你一招:学习Java必须学会的CSS用法

一&#xff1a;CSS概述什么是CSSCSS就是层叠样式表(Casading Style Sheets)&#xff0c;通常称为CSS样式表&#xff0c;或者是级联样式表。主要用于设置HTML中的文本&#xff0c;内容(字体&#xff0c;大小&#xff0c;对齐)&#xff0c;图片外形(宽高&#xff0c;边框样式&…

标准I/O库之缓冲

标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数。它也对每个I/O流自动地进行缓冲管理&#xff0c;从而避免了应用程序需要考虑这一点所带来的麻烦。 标准I/O提供了三种类型的缓冲&#xff1a; &#xff08;1&#xff09;全缓冲。这种情况下&#xff0c;在填满标…

java如何写安卓接口文档_android、java制作sdk以及自动生成文档

最近一直在做android开发&#xff0c;昨天经理让我写个接口SDK做个接口文档&#xff0c;以便后面的开发。这让我很焦灼&#xff0c;SDK怎么做&#xff1f;要是只有敲代码还好。可是那个接口文档&#xff01;&#xff01;&#xff01;文档这东西最讨厌了&#xff0c;头都大了后来…

[转载]jquery cookie的用法

原文地址:http://www.cnblogs.com/qiantuwuliang/archive/2009/07/19/1526663.html jQuery cookie是个很好的cookie插件&#xff0c;大概的使用方法如下 example $.cookie(’name’, ‘value’); 设置cookie的值&#xff0c;把name变量的值设为value example $.cookie(’name’…

21世纪的设计模式:抽象工厂模式

这是我的演讲的第二部分&#xff0c;“ 21世纪的设计模式” 。 此模式在Java代码中到处都有使用&#xff0c;尤其是在更多“企业”代码库中。 它涉及一个接口和一个实现。 该界面如下所示&#xff1a; public interface Bakery {Pastry bakePastry(Topping topping);Cake bak…

java textfield类方法_java.awt.TextField类

java.awt.TextField是一个文本框组件1.构造方法TextField()&#xff1a;创建一个默认长度为一个机器字符长的文本框TextField(int n)&#xff1a;创建一个指定长度为n个机器字符长的文本框TextField(String s)&#xff1a;创建一个文本框&#xff0c;该文本框的初始字符串为sTe…

广东金融学院java实验报告_《大学计算机Ⅰ》实验报告实验三

广东金融学院实验报告课程名称&#xff1a;大学计算机Ⅰ实验编号 及实验名称 姓 名 实验地点 指导教师蔡文璇 12-204课室 伍春晖博士实验三 中文Excel 2007实验系 别 班 级 实验时数 成 绩财经传媒系 经济秘书(2)班6学 号 实验日期 同组其他成员111602242 2011年 12 月07 日无一…

Markdown会干掉Html吗?

Markdown会干掉Html吗&#xff1f; 很明显&#xff0c;MarkDown正在已一种比病毒还快的速度传播着&#xff0c;量子的机器人语言也是深受其启发&#xff0c;当然了&#xff0c;在这个东西没搞出来之前&#xff0c;MarkDown就能干很多事情&#xff0c;比如在线编辑。 有了它&…

java动态变量名反射_Java动态性—反射 - Eclipse666的个人空间 - OSCHINA - 中文开源技术交流社区...

1.什么是动态语言&#xff1f;程序运行时&#xff0c;可以改变程序的结构或者变量类型&#xff1b;如Python&#xff0c;javaScriptfunction(){var s"var a3;var b4;" evals(s);}在执行javascript代码的的过程中&#xff0c;可以改变变量的值或插入语句改变结构。但J…

java中的module是什么意思_Angular - 组件中module.id的含义是什么?

Update for (2017-03-13) &#xff1a;删除了所有提及的moduleId . “组件相对路径”cookbook已删除我们在我们推荐的SystemJS配置中添加了一个新的SystemJS插件(systemjs-angular-loader.js) . 此插件动态地将templateUrl和styleUrls中的“组件相对”路径转换为“绝对路径” .…

HTML跳转

Window.location.href"http://www.baidu.com/"转载于:https://www.cnblogs.com/hucaihao/p/3514165.html

Spring注释,我从来没有机会使用第1部分:@primary

今天&#xff0c;我想起了我的一个老朋友&#xff08;primary&#xff09;&#xff0c;我们从教程到教程都遇到了他。 您知道在Spring Autowired批注中按类型工作&#xff0c;也就是说&#xff0c;如果Spring找到符合类型的匹配的合格bean&#xff0c;则会将其注入。让我们在示…

mysql构建栋_【转载】这次拆库 应是微服务化的拆分方式

一、现状现状.png我们将一个大而全的系统一拆为三&#xff0c;容器&#xff0c;发布&#xff0c;测试都已经独立出去&#xff0c;但是原始的数据库还是一套&#xff0c;现在需要将数据库做一个拆分&#xff0c;A、B、C三个系统有各自的数据库之后&#xff0c;我们的微服务化在现…

使用SharePoint 2010新增的文档集内容类型来管理文档

使用SharePoint 2010新增的文档集内容类型来管理文档 SharePoint 2010新增加的文档集功能是作为内容类型存在的&#xff0c;使用范围在网站集中&#xff0c;需要激活“文档集”功能到网站集才可以正常使用。文档集其实就是一个SharePoint产品增强的文件夹和内容类型的综合体现。…