例如,我想基于某些过滤器从数据库加载数据,将其转换(映射)到某些对象,限制数据并将其收集到列表中:
List<Person> people = new DbStream("PERSON").filter(...).limit(20l).map(...).collect(...);
我是否可以使用流API(可能在后台看不到JDBC)对数据库执行此操作?怎么样?
*我知道它绕过了SQL语言。只是想检查是否有办法...
答案 0 :(得分:4)
您可以使用名为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
答案 1 :(得分:0)
一个有趣的库,可以执行您要执行的操作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获取灵感。
评论中提到的另一个库是jOOQ。它不会将流调用映射到SQL,但允许您使用流畅的API编写SQL,然后使用流获取/转换结果。 E.g。
try (Stream<CityRecord> stream =
DSL.using(configuration)
.selectFrom(CITY)
.where(CITY.POPULATION.gt(10000))
.and(CITY.LAND_AREA.gt(300))) {
stream.map(...).limit(...).collect(...);
}
但是,请注意,如果将数据库推送到SQL语句中,您的数据库通常会从.map()
或.limit()
等每个子句中获益。
(免责声明:我为jOOQ背后的公司工作)。