美丽在于情人眼中。 “轻松”也是如此:
了解有关SQL结果集映射的更多信息,并轻松处理本机查询结果: http : //t.co/WH4BTlClIP #JPA #Java #JavaEE
— Thorben Janssen(@ thjanssen123) 2015年4月15日
Thorben撰写了有关JPA的非常有用的文章 ,最近他开始撰写有关JPA 2.1的新功能的精彩系列文章。 其中:结果集映射。 您可能从CTMMC或annotatiomania.com等网站知道结果集映射。 我们可以将映射过程总结如下:
a)定义映射
@SqlResultSetMapping(name = "BookAuthorMapping",entities = {@EntityResult(entityClass = Book.class,fields = {@FieldResult(name = "id", column = "id"),@FieldResult(name = "title", column = "title"),@FieldResult(name = "author", column = "author_id"),@FieldResult(name = "version", column = "version")}),@EntityResult(entityClass = Author.class,fields = {@FieldResult(name = "id", column = "authorId"),@FieldResult(name = "firstName", column = "firstName"),@FieldResult(name = "lastName", column = "lastName"),@FieldResult(name = "version", column = "authorVersion")})})
上面的映射相当简单。 它指定如何将数据库列映射到实体字段和整个实体。 然后,为该映射指定一个名称( "BookAuthorMapping"
),然后可以在整个应用程序中重用该名称,例如,使用本机JPA查询。
我特别喜欢Thorben随后写道:
如果您不希望在实体中添加如此庞大的注释块,则还可以在XML文件中定义映射
…因此,我们回到了用大量XML替换大量注释的技术–我们中的许多人都希望避免使用注释的技术…:-)
b)应用映射
在某些Java类型上静态定义了映射后,您就可以通过应用上述BookAuthorMapping
来获取这些实体
List<Object[]> results = this.em.createNativeQuery("SELECT b.id, b.title, b.author_id, b.version, " +" a.id as authorId, a.firstName, a.lastName, " + " a.version as authorVersion " + "FROM Book b " +"JOIN Author a ON b.author_id = a.id", "BookAuthorMapping"
).getResultList();results.stream().forEach((record) -> {Book book = (Book)record[0];Author author = (Author)record[1];
});
请注意,您仍然需要记住Book
和Author
类型并显式转换,因为没有可验证的类型信息真正附加到任何内容上。
“复杂”的定义
现在,该文章声称这是“复杂”映射,毫无疑问,我会同意。 如果您想通过JPA真正映射您的实体,那么只有一个简单联接的非常简单的查询已经触发了此类注释混乱。 一旦查询变得复杂一点,您就不想看到Thorben的映射注释。 记住,@ @SqlResultSetMapping
是关于映射(本机!)SQL结果的,所以我们不再处于对象图持久化领域,而是进入SQL领域 ,在该领域进行批量获取,反规范化,聚合和其他“奇特” SQL东西为王。
问题在这里:
Java 5引入了注释。 注释最初打算用作“人工修饰符”,即诸如static
, final
, protected
类的东西(有趣的是, 锡兰只知道注释,没有修饰符 )。 这很有道理。 Java语言设计人员可以在不破坏现有代码的情况下引入新的修饰符/“关键字”,因为“真实”关键字是保留字,很难在语言中引入。 还记得enum
吗?
因此,注释的好用例(而且很少)是:
-
@Override
-
@Deprecated
(尽管注释属性会很漂亮) -
@FunctionalInterface
JPA(以及其他Java EE API以及Spring)在使用注解方面一无所知。 在我之后重复:
在Java之前或之后,没有一种语言像Java那样滥用注释。
阅读以上内容时,我的内心深处充满了动感。 您还记得以下内容吗?
在Java之前或之后,没有任何一种语言比Java滥用过检查异常。
到2020年,我们都会深表遗憾。
注释是Java类型系统中的一大障碍。 它们的合理使用极为有限,而这些天我们Java Enterprise开发人员正在做的事情绝对不在“合理”的范围内。 我们正在滥用它们来配置某些我们本该为之编写代码的东西。
这是使用jOOQ (或任何其他利用SQL的泛型和类型安全性的API)运行相同查询的方式:
Book b = BOOK.as("b");
Author a = AUTHOR.as("a");DSL.using(configuration).select(b.ID, b.TITLE, b.AUTHOR_ID, b.VERSION,a.ID, a.FIRST_NAME, a.LAST_NAME,a.VERSION).from(b).join(a).on(b.AUTHOR_ID.eq(a.ID)).fetch().forEach(record -> {BookRecord book = record.into(b);AuthorRecord author = record.into(a);});
此示例结合了JPA 2.1的注释和查询。 有关计划的“实体”的所有元信息已经包含在查询中,因此也包含在fetch()
方法生成的Result
中。 但这并不重要,关键是这个lambda表达式……
record -> {BookRecord book = record.into(b);AuthorRecord author = record.into(a);
}
……可以是您想要的任何东西! 就像我们在以前的博客文章中显示的更复杂的示例一样:
- 不再需要ORM
- 使用jOOQ和JavaFX将SQL数据转换为图表
可以使用函数即时定义映射。 函数是理想的映射器,因为它们接受输入,产生输出并且完全无状态。 关于Java 8中功能的最好之处在于,它们是由Java编译器编译的,可用于对映射进行类型检查。 当给定的映射算法可以使用多次时,您可以将函数分配给对象,从而可以重用这些函数。
实际上,SQL SELECT
子句本身就是这样的功能。 将输入元组/行转换为输出元组/行的函数,您可以使用其他表达式即时修改该函数。
在前面的JPA 2.1本机SQL语句和@SqlResultSetMapping
示例中,绝对没有任何类型可以进行类型检查。 想象一下更改列名:
List<Object[]> results = this.em.createNativeQuery("SELECT b.id, b.title as book_title, " +" b.author_id, b.version, " +" a.id as authorId, a.firstName, a.lastName, " + " a.version as authorVersion " + "FROM Book b " +"JOIN Author a ON b.author_id = a.id", "BookAuthorMapping"
).getResultList();
您注意到差异了吗? b.title
列已重命名为book_title
。 在SQL字符串中。 在运行时会爆炸! 如何记住你也必须适应
@FieldResult(name = "title", column = "title")
… 成为
@FieldResult(name = "title", column = "book_title")
相反,如何记住,一旦在@FieldResult
重命名了column
,就还必须检查使用此"BookAuthorMapping"
位置,并还要更改那些查询中的列名。
@SqlResultSetMapping(name = "BookAuthorMapping",...
)
注解是邪恶的
您可能同意或不同意以上某些内容。 您可能喜欢jOOQ,也可能不喜欢jOOQ ,这是完全可以的。 但是,很难不同意以下事实:
- Java 5引入了非常有用的注释
- Java EE / Spring严重滥用了这些注释来替换XML
- 现在,我们有了Java中的并行Universe类型系统
- 该并行Universe类型系统完全没有用,因为编译器无法对其进行自省
- Java SE 8引入了函数式编程和许多类型推断
- Java SE 9-10将引入更多很棒的语言功能
- 现在很清楚,配置(XML或注释)应该首先是代码
- JPA 2.1已成为新的EJB 2.0:已过时
就像我说的。 很难不同意。 换句话说:
代码在表达算法方面比配置好得多
我在各种会议上亲自见过Thorben。 Thorben :-)这里的这句话并不是个人意思,-)您有关JPA的文章非常有趣。 如果您的读者使用的是JPA,请查看Thorben的博客: http : //www.thoughts-on-java.org 。
同时,我很想提名Thorben赢得“ 2015年年度诠释狂”的称号
翻译自: https://www.javacodegeeks.com/2015/04/how-jpa-2-1-has-become-the-new-ejb-2-0.html