【问题标题】:How can I use stream API to load data from the DB?如何使用流 API 从数据库加载数据?
【发布时间】:2016-10-10 12:52:20
【问题描述】:

例如,我想从数据库中加载数据,基于一些过滤器,将其转换(映射)到一些对象,限制数据并将其收集到一个列表中:

List<Person> people = new DbStream("PERSON").filter(...).limit(20l).map(...).collect(...);

我可以使用流 API(可能在后台看不到 JDBC)对 DB 执行此操作吗?怎么样?

* 我知道它绕过了 SQL 语言。只是想看看有没有办法......

【问题讨论】:

  • Speedment 可以帮助您:github.com/speedment/speedment
  • @assylias - jooq 似乎没有实现流 API。
  • @AlikElzin-kilaka 它可以返回您可以流式传输的集合。在 SQL 级别过滤/限制将比在 Java 级别更有效......取决于您所追求的。另请注意,jooq 有各种帮助方法将结果转换为流,例如 DSLContext.fetchStream()。

标签: java database jdbc java-8 java-stream


【解决方案1】:

您可以使用名为Speedment 的外部库来完成此操作。它们允许您从数据库的元数据生成代码,然后使用生成的类在数据库的表上进行流式传输。

在这个例子中,我们使用了一个数据库用户,它有三个字段:

-----------------------------------
- UserName - Trusted - TimeOnline -                                -
-  VARCHAR -   INT   -  BIGINT    -
-----------------------------------

流式传输示例(查找 10 名最先使用的用户):

List<String> userNames = new LinkedList<>();
userDatabase.stream()
    .sorted( Users.USER_NAME.comparator() )
    .limit( 10 )
    .forEach( p ->  {
        users.add( p.getUsername() );
    } );
return users;

示例插入:

userDatabase.newEmptyEntity()
             .setUsername( "Gikkman" )
             .setIsTrusted( 1 )
             .setTimeOnline( 0 )
             .persist();  //This command persists the entry to the DB

【讨论】:

  • 比较器长什么样子?
  • Speedment 为您的表格列生成字段,并为不同字段生成一组方法。我在上面添加了一个比较器,它将按 UserName 列对用户进行排序
  • @AlikElzin-kilaka 这个答案是你要找的,还是你还需要什么?
【解决方案2】:

做你需要做的事

JINQ 是一个有趣的库,可以满足您的需求,它执行符号字节码执行,将普通 Java 代码转换为 SQL / JPQL 或 jOOQ 查询。以下是从文档中获取的示例:

cityStream
   .where( c -> c.getPopulation() > 10000
         && c.getLandArea() > 300 );

以上将(大致)转换为以下 SQL 查询:

SELECT * FROM city c WHERE c.population > 10000 AND c.land_area > 300

或者,如果它由 JPQL 支持,它还可以生成一个完全不同的 SQL 查询,包括必要的连接,具体取决于您指定实体和关系的方式。

JINQ 的灵感来自 LINQ,I recommend reading this interesting interview with the author

几乎做你需要做的事情

cmets 中提到的另一个库是jOOQ。它不会将流调用映射到 SQL,但允许您使用流畅的 API 编写 SQL,然后使用流获取/转换结果。例如

try (Stream<CityRecord> stream =
    DSL.using(configuration)
       .selectFrom(CITY)
       .where(CITY.POPULATION.gt(10000))
       .and(CITY.LAND_AREA.gt(300))) {

    stream.map(...).limit(...).collect(...);
}

但是,请注意,如果将每个单独的子句(例如 .map().limit())推送到 SQL 语句中,您的数据库通常会从中受益。

(免责声明:我为 jOOQ 背后的公司工作)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 2011-05-30
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多