名扬数据:数据库访问因Java 8 彻底改变

通过新的函数式处理数据的方式扩展了集合(Collect类.而通常情况下java处置大量数据时需要大量的循环和迭代器Java8不只仅添加了函数式支持..

假设你有一个存储客户(Custom对象的collection例如.:

将不得不迭代所有的custom对象并只保存你需要的Collection<Customer>&nbsp;customers;如果你只对来自Belgium客户感兴趣,而且它也不怎么笼统.假使你有1千万个对象时会怎样呢?会通过两个线程并发过滤所有对象来提速么?那你将不得不使用大量危险的多线程代码来重写所有代码Collection<Customer>belgian=newArrayList<>; forCustomc:custom{     ifc.getCountri.equal"Belgium"         belgians.addc; } 这不仅花费了5行代码..

仅仅只需要一行代码就能实现相同的功能.通过对函数式编程的支持,而通过Java8.Java8能让你只写一个函数表明你对哪些客户(对象)感兴趣然后使用那个函数对集合做过滤就可以了.Java8新 SteamAPI支持你这样做,而且更容易理解.几乎没有什么 老生常谈(循环或迭代器等).代码调用了filter方法,customers.stream.filter     c->c.getCountri.equal"Belgium" ; 上面Java8版本的代码不只更短.那很明显这段代码是用来过滤客户(对象).不需要再把时间浪费在解读循环中的代码来理解它对它数据做什么.

假使你想并发执行这段代码该怎么办呢?只需使用另一个类型的stream

customers.parallelStream.filter     c->c.getCountri.equal"Belgium" ; 更另人激动的这种函数式风格的代码也同样适用于数据库

数据库上使用函数式方式,顺序员需要用特殊数据库查询语句去访问数据库的数据.例如,激进上来说.下面就是用 JDBC代码去查找来自Belgium客户:

可它只能用在通用访问查询,PreparedStats=con.prepareStat       "SELECT*"    +"FROMCustomC"    +"WHEREC.Countri=?"; s.setStr1,"Belgium"; ResultSetrs=s.executeQueri; 大部分这些代码都是字符串,这样会使编译器不能发现错误而且这草率的代码会导致平安问题.还有这些大量的样板代码使得写数据访问代码变得十分冗余.一些工具例如 jOOQ通过使用特殊的java库去提供数据库查询语言可以解决错误检查和安全问题。或者使用对象关系映射工具可以免去大量的无趣的代码。如果需要复杂的查询,还是需要用特殊的数据库查询语言。

探索怎样的未来数据库API可以令函数式编程成为可能。这里就是一个使用Jinq数据库查询使用Java8,借助流式API就可以用函数式方式去查询数据库了例如,Jinq一个开源的项目。

未来的Jinq版本可以让你用流式API直接写数据库查询。当代码运行的时候,customers.wher     c->c.getCountri.equal"Belgium" ; 这代码几乎跟跟使用流式API代码一样.事实上。Jinq将自动翻译成数据库查询代码,正如之前JDBC查询一样。

就算没有学过一些新的数据库查询语言,这样的话。也可以写出有效率的数据库查询。可以用同样样式的代码用在java集合上。也不需要特殊的java编译器或者虚拟机。所有的代码编译和运行在普通的java8JDK上。如果你代码有错误,编译器将找出它并且演讲给你就像普通的java代码。

Jinq能够翻译下面的数据库查询,尽管它很复杂。Jinq支持跟SQL92一样的复杂查询.Select选择),project投影),join连接),和子查询 都支持。翻译java代码成数据库查询的算法是十分灵活的只要是能接受的都能翻译。例如。

甚至复杂的查询也能够胜任。customers     .wherec->c.getCountri.equal"Belgium"     .wherec->{         ifc.getSalari<100000             returnc.getSalari<c.getDebt;         else            returnc.getSalari<2*c.getDebt;         }; 正如你看到java8函数式编程非常适合数据库查询。而且查询紧凑。

内部运作,但这都是如何工作的呢?怎么能让普通的Java编译器将Java代码转换成数据库查询?Java8有什么特别之处使这个成为可能?

但 Jinq能够在被编译的Java代码运行时进行分析并从中构建数据库查询。使用 Java8StreamAPI时,支持这些函数性风格的新的数据库PI关键是一种叫做“象征性执行”字节码分析手段。虽然你代码是被一个普通的Java编译器编译的并运行在一个普通的Java虚拟机中。常会发现分析短小的函数时,象征性执行的工作效果最好。

要了解这个象征性执行是如何工作的最简单的方法是用一个例子。让我检查一下下面的查询是如何被 Jinq转换为SQL查询语言的

其对应的数据库查询是customers     .wherec->c.getCountri.equal"Belgium" 初始时,变量 custom一个集合。

where方法被调用,SELECT*   FROMCustomC 然后。一个函数被传递给它where方法中,Jinq打开这个函数的.class文件,得到这个函数被编译成的字节码进行分析。这个例子中,不使用真正的字节码,让我用一些简单的指令来代表这个函数的字节码:

d=c.getCountri

e=&#8220;Belgium&#8221;

=d.equale

returne

假设函数已被Java编译器编译成这四条指令。当调用 where方法时,这里。Jinq看到就是这些。如何才干使Jinq理解这些代码呢?

Jinq使用符号来表示执行代码时的所有值。这就是这个分析为什么被称为“象征性执行”Jinq通过执行代码来分析。但 Jinq不直接运行代码。笼统”地运行代码:不使用真实的变量和真实的值。

并跟踪所有的副作用或代码在顺序状态时改变的所有东西。下面是一个图表,Jinq执行每条指令。显示出 Jinq用象征性执行方式执行这四行代码时发现的所有副作用。

象征性执行的例子,可以看到第一条指令运行后,图中。Jinq发现了两个副作用:变量d已经发生了变化,方法 Customer.getCountri被调用。由于是象征性执行,变量d没有给出一个真正的比方是USA 或“Denmark值,被分配为 c.getCountri象征性的值。

Jinq对副作用作精简。由于变量 d和 e局部变量,所有这些指令被象征性执行之后。任何变化在函数退出后都会被丢弃,所以这些副作用可以忽略不计。Jinq也知道 Customer.getCountriandString.equ方法没修改任何变量或显示任何输出,因此这些方法调用也可以被忽略。由此,Jinq可以得出这样的结论:执行这个函数只会发生一个作用,会返回 c.getCountri.equal"Belgium"

可以混合数据库查询方面的知识,一旦Jinq已明白在where方法中传递给它函数。优先于 custom集合来创建一个新的数据库查询。

生成数据库查询,这种方法对于不同的Java编译器输出的不同的代码模式都是相当强大的如果 Jinq遇到代码有不能转化为数据库查询的副作用,这就是Jinq如何从你代码生成数据库查询的象征性执行的使用意味着。Jinq将保持你这些代码不变。因为一切都是用正常的Java代码写的Jinq可以直接运行那些代码,您的代码将产生预期的结果。

这些算法可以正确地从你代码生成数据库查询。这个简单的翻译实例应该让你明白了怎样查询翻译作品。可以确信。