Home  >  Article  >  Java  >  Database CRUD operations in Java 8 Streams

Database CRUD operations in Java 8 Streams

高洛峰
高洛峰Original
2017-02-08 11:09:561529browse

Background

Speedment is an open source tool set that can be used to generate Java entities and manage our communication process with the database. You can use a graphical tool to connect to the database and generate a complete set of ORM framework code to represent the domain model. But Speedment is more than just a code generator, it's a runtime program that can be plugged into your application, making it possible to translate your Java 8 streaming code into optimized SQL queries. This is also a part that I will talk about specifically in this article.

Generate code

To start using Speedment in a Maven project, you need to add the following lines of code to your pom.xml file. In this example, I'm using MySQL, but you can also choose to use PostgreSQL or MariaDB. Proprietary databases like Oracle are available for enterprise customers.

Pom.xml

<properties>
  <speedment.version>3.0.1</speedment.version>
  <db.groupId>mysql</db.groupId>
  <db.artifactId>mysql-connector-java</db.artifactId>
  <db.version>5.1.39</db.version></properties><dependencies>
  <dependency>
    <groupId>com.speedment</groupId>
    <artifactId>runtime</artifactId>
    <version>${speedment.version}</version>
    <type>pom</type>
  </dependency>

  <dependency>
    <groupId>${db.groupId}</groupId>
    <artifactId>${db.artifactId}</artifactId>
    <version>${db.version}</version>
  </dependency></dependencies><build>
  <plugins>
    <plugin>
      <groupId>com.speedment</groupId>
      <artifactId>speedment-maven-plugin</artifactId>
      <version>${speedment.version}</version>

      <dependencies>
        <dependency>
          <groupId>${db.groupId}</groupId>
          <artifactId>${db.artifactId}</artifactId>
          <version>${db.version}</version>
        </dependency>
      </dependencies>
    </plugin>
  </plugins></build>

Now you have access to a number of new Maven repositories that make it easier to use this toolkit. To start the Speedment UI, execute the following command:

mvn speedment:tool

This will lead you through a process to connect to the database and configure code generation. The easiest way to start is to run it with the default settings first. When you press the Generate button, Speedment will analyze your database metadata and add classes like entities and entity managers to your project.

Initializing Speedment

After your domain model is generated, setting up Speedment is easy. Create a new Main.java file and add the following lines of code. The classes you see are generated, so they are named based on the database schema, table, and column names.

Main.java

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

The above code creates a new application entity using a generated constructor pattern. The constructor makes it possible to set any runtime configuration details, such as the database password.

When we have an application entity, we can use it to access the generated entity manager. Here, I have four tables in my database; “hare”, “carrot”, “human”, and “friend”. (You can find the full database definition here).

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

Now these entity managers can be used to perform all CRUD operations.

Creating entities

The way to create entities is very straightforward. We just use the implementation of entity generation, set the column value and persist it to the data source.

hares.persist(  new HareImpl()    .setName("Harry")    .setColor("Gray")    .setAge(8)
);

persist method returns a (potentially) new instance of Hare with auto-generated keys like "id" already set. If we want to continue to use Harry after persistence, we can use this returned by the persist method:

final Hare harry = hares.persist(  new HareImpl()
    .setName("Harry")
    .setColor("Gray")
    .setAge(8)
);

If the persistence operation fails, for example, if a foreign key violates the unique constraint, there will be A SpeedmentException is thrown. We should check this and if there is something implicit that would prevent us from persisting this hare record, we should display an error message.

try {  final Hare harry = hares.persist(
    new HareImpl()
      .setName("Harry")
      .setColor("Gray")
      .setAge(8)
  );
} catch (final SpeedmentException ex) {  System.err.println(ex.getMessage());  return;
}

Reading Entities

The coolest feature of the Speedment runtime is the ability to use Java 8's Stream API to stream data in the database. “Why would this be cool?” you might ask yourself. "Even Hibernate supports streaming operations these days!" was the answer.

The best thing about using Speedment streaming operations is that they take into account both the intermediate and terminating actions of building the stream. This means that if you add a filter to the stream after it has been created, the filter will also be taken into account when constructing the SQL statement.

Here is an example where we want to count the total number of hare records in the database.

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

The SQL query that this code will generate is as follows:

SELECT COUNT(id) FROM hares.hare;

The termination operation here is .count(), so Speedment knows to create a SELECT COUNT(...) statement. It also knows that the primary key of the "hare" table is the "id" column, so it is possible to reduce the entire statement sent to the database to this.

A more complex example might be to find the number of rabbits whose name starts with "rry" and whose age is 5 or greater. This can be written like this:

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

We define the filter using the located builder generated for us by Speedment. This makes it possible for us to programmatically analyze the stream and reduce it to a SQL statement like this:

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

If we add a Speedment operation that cannot optimize the stream, it will behave like a normal Java 8 streams are handled. We will never limit the use of generated location builders, which can make streaming operations more efficient.

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

The above code will produce an extremely inefficient statement as follows, but it can still run.

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

Updating entities

Updating existing entities is very similar to reading and persisting entities. Changes to the local copy of the entity will not affect the database contents until we call the update() method.

Below, we take the Harry we created previously using Hare and change his color to brown:

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

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

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

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

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

try {
  hares.stream()
    .filter(Hare.NAME.equal("Harry"))
    .map(Hare.COLOR.setTo("Brown"))
    .forEach(hares.updater());
} catch (final SpeedmentException ex) {  System.err.println(ex.getMessage());  return;
}

实体删除

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

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

总结

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

更多Java 8 Streams 中的数据库 CRUD 操作相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn