Java中怎么利用Streams对数据库进行查询操作
Java中怎么利用Streams对数据库进行查询操作,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
示例数据库
我们使用的示例数据库是Sakila。它有Film(影片), Actor(演员), Category(类别)等表格,下载地址:https://dev.mysql.com/doc/index-other.html。
步骤一:连接数据库
我们使用Speedment Initializer配置pom.xml文件,点击下载后,将得到一个带有自动生成Main.java文件的项目文件夹。
然后,解压文件夹zip.,打开命令行,然后转到pO.xml文件所在的位置。输入以下命令:
mvnspeedment:tool
Speedment将被启动,会提示您输入授权码。选择“Start Free”,您将获得免费许可。然后便可以连接数据库开始使用。
步骤二:生成代码
当数据库开始加载schema data时,便可以点击"Generate"生成完整的Java域模型。
步骤三:编写应用程序代码
步骤二中还会自动生成一个Speedment的生成器。打开Main.java文件,将main()方法中的代码替换成以下代码:
SakilaApplicationapp=newSakilaApplicationBuilder().withPassword("sakila-password")//Replacewithyourownpassword.build();
接下来,我们将编写一个打印出所有影片的应用程序。当然这只是一个小程序,我们还要对其进行改进。
//ObtainsaFilmManagerthatallowsusto//workwiththe"film"tableFilmManagerfilms=app.getOrThrow(FilmManager.class);//Createastreamofallfilmsandprint//eachandeveryfilmfilms.stream().forEach(System.out::println);
运行时,Java stream将自动生成SQL。为了查看SQL代码,需要修改Application Builder,并使用STREAM日志类型开启日志记录。
SakilaApplicationapp=newSakilaApplicationBuilder().withPassword("sakila-password").withLogging(ApplicationBuilder.LogType.STREAM).build();
以下是运行应用程序时的SQL代码:
SELECT`film_id`,`title`,`description`,`release_year`,`language_id`,`original_language_id`,`rental_duration`,`rental_rate`,`length`,`replacement_cost`,`rating`,`special_features`,`last_update`FROM`sakila`.`film`,values:[]
SQL代码会因您选择的数据库类型而异(例如MySQL,MariaDB,PostgreSQL,Oracle,MS SQL Server,DB2,AS400等),且这些变化都是自动的。
上面的代码将产生以下输出(简洁为主)
FilmImpl{filmId=1,title=ACADEMYDINOSAUR,...,length=86,...}FilmImpl{filmId=2,title=ACEGOLDFINGER,...,length=48,...}FilmImpl{filmId=3,title=ADAPTATIONHOLES,...,length=50,...}...
步骤四:使用过滤器
Speedment流包括过滤器在内的所有流操作。假设我们只想过滤掉那些超过60分钟的影片,可以通过以下代码来实现:
films.stream().filter(Film.LENGTH.greaterThan(60)).forEach(System.out::println);
生成SQL:
SELECT`film_id`,`title`,`description`,`release_year`,`language_id`,`original_language_id`,`rental_duration`,`rental_rate`,`length`,`replacement_cost`,`rating`,`special_features`,`last_update`FROM`sakila`.`film`WHERE(`length`>?),values:[60]
生成输出:
FilmImpl{filmId=1,title=ACADEMYDINOSAUR,...,length=86,...}FilmImpl{filmId=4,title=AFFAIRPREJUDICE,...,length=117,...}FilmImpl{filmId=5,title=AFRICANEGG,...length=130,...}
可以通过组合过滤器来创建更复杂的表达式,如下所示:
films.stream().filter(Film.LENGTH.greaterThan(60).or(Film.LENGTH.lessThan(30))).forEach(System.out::println);
这将回收掉那些不到30分钟或者超过一小时的影片。这时检查您的日志文件,您将发现这个流已生成SQL。
步骤五:定义元素的顺序
默认情况下,出现在流中的元素是未被定义的。想要定义一个特定顺序,您需要将SORTED()操作应用到这样的流:
films.stream().filter(Film.LENGTH.greaterThan(60)).sorted(Film.TITLE).forEach(System.out::println);
生成SQL
SELECT`film_id`,`title`,`description`,`release_year`,`language_id`,`original_language_id`,`rental_duration`,`rental_rate`,`length`,`replacement_cost`,`rating`,`special_features`,`last_update`FROM`sakila`.`film`WHERE(`length`>?)ORDERBY`length`ASC,values:[60]
生成输出:
FilmImpl{filmId=77,title=BIRDSPERDITION,...,length=61,...}FilmImpl{filmId=106,title=BULWORTHCOMMANDMENTS,...,length=61,}FilmImpl{filmId=114,title=CAMELOTVACATION,...,length=61,..}...
您还可以组合多种分类机来定义主顺序、次顺序等。
films.stream().filter(Film.LENGTH.greaterThan(60)).sorted(Film.LENGTH.thenComparing(Film.TITLE.reversed())).forEach(System.out::println);
这将按照LENGTH顺序(升序)和TITLE顺序(降序)对影片元素进行排序。您可以对数量字段进行任意组合。
注意:如果您按升序组成两个或两个以上字段时,你应该使用.comparator(). I.e.字段方法。例如:sorted(Film.LENGTH.thenComparing(Film.TITLE.comparator()))。
步骤六:避免大对象块(Large Object Chunks)
人们一般会对结果进行分页来避免使用不必要的大对象块(Large Object Chunks)。假设我们希望在每页看到50个元素,我们可以通过以下代码来实现:
privatestaticfinalintPAGE_SIZE=50;publicstatic<T>Stream<T>page(Manager<T>manager,Predicate<?superT>predicate,Comparator<?superT>comparator,intpageNo){returnmanager.stream().filter(predicate).sorted(comparator).skip(pageNo*PAGE_SIZE).limit(PAGE_SIZE);}
该方法可以使用任意过滤器对任意表进行随意排序。
例如,调用:
page(films,Film.LENGTH.greaterThan(60),Film.TITLE,3)
将回收掉那些超过60分钟的影片流,并按照第三页的标题进行排序(即,跳过150部影片并显示以下50部影片)。
生成SQL
SELECT`film_id`,`title`,`description`,`release_year`,`language_id`,`original_language_id`,`rental_duration`,`rental_rate`,`length`,`replacement_cost`,`rating`,`special_features`,`last_update`FROM`sakila`.`film`WHERE(`length`>?)ORDERBY`title`ASCLIMIT?OFFSET?,values:[60,50,150]
生成输出
FilmImpl{filmId=165,title=COLDBLOODEDDARLING,...length=70,...}FilmImpl{filmId=166,title=COLORPHILADELPHIA,...,length=149...}FilmImpl{filmId=167,title=COMAHEAD,...length=109,...}...
同样,如果我们使用了另一种数据库类型,那么SQL代码就会不同。
步骤七: In-JVM-Memory加速
由于您在初始化程序中使用了标准配置,所以In-JVM-memory加速在POM.XML文件中就被启动。如果要激活应用程序中的加速,只需要将初始代码修改成如下代码:
SakilaApplicationapp=newSakilaApplicationBuilder().withPassword("sakila-password").withBundle(InMemoryBundle.class).build();//Loaddatafromthedatabaseintoanin-memorysnapshotapp.getOrThrow(DataStoreComponent.class).load();
关于Java中怎么利用Streams对数据库进行查询操作问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。