Java 8 Streams中的数据库CRUD操作

简介:


接触一个新工具的时候,刚开始要克服的最大障碍就是如何让你自己先尝试做出一个小东西来。现在你也许对 Java 8 中新的 Stream API 的运作方式在理解上比较自信,但你也许并没用它来进行过数据库查询操作。为了帮助你开始使用 Stream API 来对 SQL 数据库进行创建、修改和读取操作, 我已经在这个快速开始的教程中把它们整合到了一起。希望它能帮助你提升对流式API的使用水平!

背景

Speedment 是一个开放源代码的工具集,它可以被用来生成 Java 实体,并且能将我们同数据库的通信过程管理起来。你可以利用一个图形工具连接到数据库并生成出一套完整的 ORM 框架代码来表示域模型。但是 Speedment 不单单只是一个代码生成器而已,它还是一个能插入应用程序中的运行时程序,这样就有可能将你的 Java 8 流式代码翻译成优化过的SQL查询。这也是我将会在本文中专门讲述的一个部分。

生成代码

要在一个 Maven 工程中开始使用 Speedment,需要你将下面几行代码添加到你的 pom.xml 文件中。在本例中,我使用的是 MySQL,而你也可以选择使用 PostgreSQL 或者 MariaDB。面向于像Oracle这样的专有数据库可用于企业级客户。

Pom.xml


 
 
  1. <properties> 
  2.   <speedment.version>3.0.1</speedment.version> 
  3.   <db.groupId>mysql</db.groupId> 
  4.   <db.artifactId>mysql-connector-java</db.artifactId> 
  5.   <db.version>5.1.39</db.version> 
  6. </properties>  
  7. <dependencies> 
  8.   <dependency> 
  9.     <groupId>com.speedment</groupId> 
  10.     <artifactId>runtime</artifactId> 
  11.     <version>${speedment.version}</version> 
  12.     <type>pom</type> 
  13.   </dependency>  
  14.   <dependency> 
  15.     <groupId>${db.groupId}</groupId> 
  16.     <artifactId>${db.artifactId}</artifactId> 
  17.     <version>${db.version}</version> 
  18.   </dependency> 
  19. </dependencies>  
  20. <build> 
  21.   <plugins> 
  22.     <plugin> 
  23.       <groupId>com.speedment</groupId> 
  24.       <artifactId>speedment-maven-plugin</artifactId> 
  25.       <version>${speedment.version}</version>  
  26.       <dependencies> 
  27.         <dependency> 
  28.           <groupId>${db.groupId}</groupId> 
  29.           <artifactId>${db.artifactId}</artifactId> 
  30.           <version>${db.version}</version> 
  31.         </dependency> 
  32.       </dependencies> 
  33.     </plugin> 
  34.   </plugins> 
  35. </build> 

现在你可以访问到许多新的 Maven 资源库,它们能让你更加轻松的使用这个工具包。要启动 Speedment UI, 执行如下命令:


 
 
  1. mvn speedment:tool 

这样就会有一个过程引导你连接到数据库并对代码生成进行配置。一开始最简单的方法就是用默认的设置先跑起来再说。当你按下生成按钮“Generate,” Speedment 就会对你的数据库元数据进行分析,然后在你的工程中添加像实体和实体管理器这样的类。

初始化 Speedment

当你的域模型生成好了以后,Speedment 的设置就容易了。创建一个新的 Main.java 文件然后添加如下几行代码。你看到的类都是生成的,因此它们的命名都是根据数据库模式、表以及列的名称来决定的。

Main.java  

  1. public class Main {  
  2. public static void main(String... param) {  
  3. final HaresApplication app = new HaresApplicationBuilder()  
  4. .withPassword("password")  
  5. .build();  
  6. }  

上面的代码创建了一个新的应用程序实体,它使用了一种生成的构造器模式。构造器是的对任何运行时配置细节的设置成为可能,例如数据库的密码。

当我们有了一个应用实体,就可以用它来访问生成的实体管理器了。在这里,我的数据库中有了四个表; “hare”, “carrot”, “human”, 以及 “friend”. (你可以在这里找到完整的数据库定义)。


 
 
  1. final CarrotManager carrots = app.getOrThrow(CarrotManager.class);  
  2. final HareManager hares = app.getOrThrow(HareManager.class);  
  3. final HumanManager humans = app.getOrThrow(HumanManager.class);  
  4. final FriendManager hares = app.getOrThrow(FriendManager.class); 

现在这些实体管理器可以被用来执行所有的CRUD操作了。

创建实体

创建实体的方式非常直接。我们就使用实体生成的实现,把列的值设置好然后持久化到数据源就可以了。


 
 
  1. hares.persist(  
  2. new HareImpl()  
  3. .setName("Harry")  
  4. .setColor("Gray")  
  5. .setAge(8) 
  6.  ); 

persist 方法会返回一个 (潜在的) Hare 新实例,里面像“id”这种自动生成键已经设置好了。如果我们想在持久化之后继续使用 Harry, 那就可以使用 persist 方法返回的这个:


 
 
  1. final Hare harry = hares.persist(  
  2. new HareImpl()  
  3. .setName("Harry")  
  4. .setColor("Gray")  
  5. .setAge(8)  
  6. ); 

如果持久化操作失败了,例如如果有一个外键违反了唯一性约束,就会有一个 SpeedmentException 抛出。我们应该对此进行检查,如果有默写东西会阻止我们对这条 hare 记录进行持久化,就应该显示一条错误信息。


 
 
  1. try {  
  2. final Hare harry = hares.persist(  
  3. new HareImpl()  
  4. .setName("Harry")  
  5. .setColor("Gray")  
  6. .setAge(8)  
  7. );  
  8. } catch (final SpeedmentException ex) {  
  9. System.err.println(ex.getMessage());  
  10. return;  

读取实体

Speedment 运行时中最酷的功能特性就是能够使用 Java 8 的 Stream API对数据库中的数据进行流式操作。“为什么这样做会很酷呢?” 你可能会这样问你自己。“如今甚至Hibernate 都已经支持流式操作了!”这就是回答。

使用 Speedment 流式操作最美好的事情就是它们把构建流的中间和终止动作都考虑进去了。这就意味着如果你在流已经被创建之后添加一个过滤器进去,那么在构建 SQL 语句时这个过滤器也会被考虑进去。

下面是一个示例,我们想要计算数据库中 hare 记录的总数。


 
 
  1. final long haresTotal = hares.stream().count();  
  2. System.out.format("There are %d hares in total.%n", haresTotal); 

这段代码将会生成的SQL查询如下:


 
 
  1. SELECT COUNT(id) FROM hares.hare; 

这里的终止操作就是 .count() ,因此 Speedment 就知道是要创建一个 SELECT COUNT(…) 语句。它也知道 “hare”表的主键是“id”这个列,如此就有可能将发送给数据库的整个语句 减少到这个样子。

更加复杂的示例可能就是找出名称以 “rry” 并且年龄大于等于 5 的兔子的数量。这个可以这样写:


 
 
  1. final long complexTotal = hares.stream()  
  2. .filter(Hare.NAME.endsWith("rry"))  
  3. .filter(Hare.AGE.greaterOrEqual(5))  
  4. .count(); 

我们使用由 Speedment 为我们生成的位于构建器来定义过滤器。这使得我们以编程的方式对流进行分析并且将其简化到如下这样一条SQL语句成为可能:


 
 
  1. SELECT COUNT(id) FROM hares.hare  
  2. WHERE hare.name LIKE CONCAT("%", ?)  
  3. AND hare.age >= 5; 

如果我们添加了一个 Speedment 不可以对流进行优化的操作, 它就会像一般的 Java 8 流那被处理。我们永远都不会限制生成的位于构建器的使用,它能是流式操作更加的高效。


 
 
  1. final long inefficientTotal = hares.stream()  
  2. .filter(h -> h.getName().hashCode() == 52)  
  3. .count(); 

上述代码会产生一条如下极其低效的语句,但是它仍然可以跑起来。


 
 
  1. SELECT id,name,color,age FROM hares.hare; 

更新实体

更新存在的实体和读取以及持久化实体非常相似。在我们调用update()方法之前,对实体本地拷贝的改变,不会影响数据库内容。

下面,我们拿到之前使用Hare创建的Harry,并将他的颜色变为棕色:


 
 
  1. harry.setColor("brown");  
  2. final Hare updatedHarry = hares.update(harry); 

如果更新被接受了,那么管理器会返回hare的一个新的拷贝,因为我们在后面会继续使用这个实例。就想做“创建”的例子中,更新可能会失败。也许颜色被定义为“值唯一”,棕色已经存在于hare中。那样的话,会抛出一个SpeedmentException异常.

我们也可以通过合并多个实体到一个流中来同时更新他们。加入我们想将所有名字为Harry的hare变为棕色,我们可以这样做:


 
 
  1. hares.stream()  
  2. .filter(Hare.NAME.equal("Harry")) 
  3. .map(Hare.COLOR.setTo("Brown"))  
  4. .forEach(hares.updater()); // 更新流中存在的元素 

我们还应该使用try-catch语句来确保在运行过程中有失败发生时警告用户。


 
 
  1. try {  
  2. hares.stream()  
  3. .filter(Hare.NAME.equal("Harry"))  
  4. .map(Hare.COLOR.setTo("Brown"))  
  5. .forEach(hares.updater());  
  6. } catch (final SpeedmentException ex) {  
  7. System.err.println(ex.getMessage());  
  8. return
  9.  } 

实体删除

我们需要知道的最后一个 CRUD 操作就是从数据库中删除实体。这个操作几乎和“更新”操作时等同的。假如说我们要把年龄超过10岁的兔子的记录都删除,就要这样做:


 
 
  1. try {  
  2. hares.stream()  
  3. .filter(Hare.AGE.greaterThan(10))  
  4. .forEach(hares.remover()); // Removes remaining hares  
  5. } catch (final SpeedmentException ex) {  
  6. System.err.println(ex.getMessage());  
  7. return;  

总结

通过阅读本文你已经了解了如何在一个 Maven 工程中对 Speedment 进行设置,还有如何使用 Java 8 的 Stream API 来从数据库中创建、更新、读取以及删除实体。这是你可以利用 Speedment 所能进行的操作的一个小的子集, 但已经是一个能让你上手的好的开始了。更多的示例以及更加高级的使用场景可以在GitHub-page上找到。


作者:佚名

来源:51CTO

相关文章
|
2月前
|
关系型数据库 MySQL Java
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
90 0
|
29天前
|
XML Java 数据库连接
性能提升秘籍:如何高效使用Java连接池管理数据库连接
在Java应用中,数据库连接管理至关重要。随着访问量增加,频繁创建和关闭连接会影响性能。为此,Java连接池技术应运而生,如HikariCP。本文通过代码示例介绍如何引入HikariCP依赖、配置连接池参数及使用连接池高效管理数据库连接,提升系统性能。
55 5
|
23天前
|
JSON Java 关系型数据库
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
36 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
|
1月前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
30 2
|
1月前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
49 3
|
1月前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
58 2
|
1月前
|
Java 数据库连接 数据库
如何构建高效稳定的Java数据库连接池,涵盖连接池配置、并发控制和异常处理等方面
本文介绍了如何构建高效稳定的Java数据库连接池,涵盖连接池配置、并发控制和异常处理等方面。通过合理配置初始连接数、最大连接数和空闲连接超时时间,确保系统性能和稳定性。文章还探讨了同步阻塞、异步回调和信号量等并发控制策略,并提供了异常处理的最佳实践。最后,给出了一个简单的连接池示例代码,并推荐使用成熟的连接池框架(如HikariCP、C3P0)以简化开发。
51 2
|
2月前
|
Java 关系型数据库 MySQL
如何用java的虚拟线程连接数据库
本文介绍了如何使用Java虚拟线程连接数据库,包括设置JDK版本、创建虚拟线程的方法和使用虚拟线程连接MySQL数据库的示例代码。
60 6
如何用java的虚拟线程连接数据库
|
1月前
|
Java 数据库连接 数据库
优化之路:Java连接池技术助力数据库性能飞跃
在Java应用开发中,数据库操作常成为性能瓶颈。频繁的数据库连接建立和断开增加了系统开销,导致性能下降。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接,显著减少连接开销,提升系统性能。文章详细介绍了连接池的优势、选择标准、使用方法及优化策略,帮助开发者实现数据库性能的飞跃。
31 4
|
1月前
|
Java 数据库连接 数据库
深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能
在Java应用开发中,数据库操作常成为性能瓶颈。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接、减少连接建立和断开的开销,从而显著提升系统性能。文章介绍了连接池的优势、选择和使用方法,以及优化配置的技巧。
31 1