几天前,我读了Iu Ming-Yee关于JINQ的有趣采访 。 顾名思义,JINQ是一种尝试提供类似于LINQ for Java的尝试。 基本思想是缩小在关系数据模型上执行查询的面向对象代码之间的语义鸿沟。 关系数据库模型的查询应轻松集成到代码中,以使其感觉更自然。
LINQ背后的研究得出的结论是,将代码转换为关系数据库查询的算法最适合功能代码。 当Java 8附带流API时,作者使用它来实现Java博士学位的想法。
为了弄清我们的手,我们从一个简单的项目开始,该项目使用Hibernate over JPA以及H2数据库和JINQ:
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>${jee.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.jinq</groupId>
<artifactId>jinq-jpa</artifactId>
<version>1.8.10</version>
</dependency>
</dependencies>
为了使用JINQ流,我们必须创建一个将EntityManagerFactory
作为参数的提供程序:
EntityManagerFactory factory = Persistence.createEntityManagerFactory("PersistenceUnit");
JinqJPAStreamProvider streams = new JinqJPAStreamProvider(factory);
将一些人插入我们的数据库后,我们可以轻松地查询他们:
List<String> firstNames = streams.streamAll(entityManager, Person.class)
.map(Person::getFirstName)
.collect(toList());
firstNames.forEach(System.out::println);
使用先前创建的JinqJPAStreamProvider
streamAll()
方法,我们可以访问数据库中的所有人员。 在这个简单的例子中,我们只想输出每个人的名字; 因此,我们map
列表并将所有结果collect
到List
。 使用forEach()
方法和对println()
方法的引用来打印此列表。
看一下生成的SQL代码,我们看到选择了所有列:
select
person0_.id as id1_4_,
person0_.FIRST_NAME as FIRST_NA2_4_,
person0_.ID_CARD_ID as ID_CARD_4_4_,
person0_.LAST_NAME as LAST_NAM3_4_,
from
T_PERSON person0_
当然,我们可以使用select()
方法来优化语句:
List<String> firstNames = streams.streamAll(entityManager, Person.class)
.select(Person::getFirstName)
.where(p -> p.equals("Homer"))
.collect(toList());
firstNames.forEach(System.out::println);
此外,我们还添加了一个谓词( where firstName = 'Homer'
):
select
person0_.FIRST_NAME as FIRST_NA2_4_
from
T_PERSON person0_
where
person0_.FIRST_NAME='Homer'
留下这个简单的示例,我们现在要创建一个查询,以选择在时间和物质项目中工作的所有具有“ Christian”名字的怪胎:
List<String> geeks = streams.streamAll(entityManager, Project.class)
.where(p -> p.getProjectType() == Project.ProjectType.TIME_AND_MATERIAL)
.joinList(Project::getGeeks)
.where(g -> g.getTwo().getFirstName().equals("Christian"))
.map(p -> p.getTwo().getFirstName())
.collect(toList());
geeks.forEach(System.out::println);
从上面的代码可以看出,我们使用第一个where()
子句来选择所有时间和材料项目。 joinList()
调用连接了怪胎表,而随后的where()
子句还限制为仅选择名字为“ Christian”的怪胎。 等等,这就是创建的SQL查询:
select
geek2_.FIRST_NAME as col_0_0_
from
T_PROJECT project0_
inner join
T_GEEK_PROJECT geeks1_
on project0_.id=geeks1_.PROJECT_ID
inner join
T_GEEK geek2_
on geeks1_.GEEK_ID=geek2_.id
where
project0_.projectType='TIME_AND_MATERIAL'
and geek2_.FIRST_NAME='Christian' limit ?
结束语 :前一段时间使用JPA的标准API,我必须说,使用JINQ的第一步更直观,更容易写下。 通过使用Java 8中的流,JINQ确实有助于缩小关系数据库世界之间的鸿沟。
翻译自: https://www.javacodegeeks.com/2016/04/using-jinq-jpa-h2.html