当您与开发人员讨论将对象映射到关系数据库时,他们经常抱怨JPA性能差,JPA提供程序的行为不可预测等。通常,在对话的某些时候,您会听到: “让我们完全放弃这项技术,我们在上个月的会议上看到了更好的东西。 我们将在我们的项目中使用它而不是JPA,并从此以后快乐地开发它们。” - 听起来很熟悉? 学习新技术没错,事实上,您应该不断地做下去,以提高您的技能和知识,但是当您遇到其中一种问题时,您会选择一条通向另一种技术的简单途径还是会问自己: “我是吗? 以正确的方式使用它?” 让我们看一下JPA用法示例。 假设我们有简单的数据库,映射到实体:
而且我们必须显示所有员工姓名,无论其雇主(和部门)如何。 没有比这容易的事了-简单的JPQL查询就能做到:
select employee from Employee employee order by employee.name
许多开发人员在这一点上完成工作,并与Friends一起庆祝他们生活中另一个成功的JPQL查询,但是我们当中有些人感到这种奇怪的感觉,即有些令人毛骨悚然的东西潜伏在光亮的表面之下。 JPA提供程序(例如Hibernate)产生的SQL查询将揭示事实:
select [...] from EMPLOYEE employee0_ order by employee0_.EMPLOYEE_NAMENothing special, so far , but here comes the naked truth:select [...] from DEPARTMENT department0_ left outer join EMPLOYER employer1_ on department0_.EMPLOYER_ID=employer1_.EMPLOYER_ID where department0_.DEPARTMENT_ID=?select [...] from EMPLOYER employer0_ where employer0_.EMPLOYER_ID=?select [...] from DEPARTMENT department0_ left outer join EMPLOYER employer1_ on department0_.EMPLOYER_ID=employer1_.EMPLOYER_ID where department0_.DEPARTMENT_ID=?select [...] from DEPARTMENT department0_ left outer join EMPLOYER employer1_ on department0_.EMPLOYER_ID=employer1_.EMPLOYER_ID where department0_.DEPARTMENT_ID=?select [...] from DEPARTMENT department0_ left outer join EMPLOYER employer1_ on department0_.EMPLOYER_ID=employer1_.EMPLOYER_ID where department0_.DEPARTMENT_ID=?
有没有搞错?! 这些查询是什么? –好吧,原因在于@ManyToOne批注的默认访 存属性值,即EAGER 。 我的数据库包含2个雇主,其中一个拥有4个部门,而第二个则没有。 加载Employee时,默认情况下,JPA提供程序会加载所有EAGER关联(在我们的示例中是Department和Employer),因此我们还有其他查询。 如上所示,JPA提供者足够聪明,可以在可能的情况下立即加载雇主和部门。
您刚刚发现了神奇的JPQL查询,可一次获取所有数据库内容 。 这种情况会让您想起过去的事情吗? 我们对于它可以做些什么呢? –我的朋友,您所需要的只是懒惰–除非真正需要,否则不要使用EAGER (请记住, @ ManyToOne和@OneToOne注释默认使用它)。
此时您可能称我为疯子或懒惰极端主义者,并问:您是否遇到过LazyInitializationException ,兄弟! 您是否听说过延迟加载问题的所有麻烦!? 性能下降等。。。我当然这样做了,但是您不认为如果我们在JPA方面遇到麻烦,也许我们会以错误的方式使用它! 我们通常在Web应用程序中所做的是在UI上呈现或编辑一些数据,并且通常只是特定实体属性的一小部分。 要做到这一点,需要从数据库中获取实体树–我们不知不觉中就问实体管理器:给我所有员工,按名称排序,以及所有相关实体,然后抱怨性能下降! 我们不在乎从数据库中获取什么,因为实体管理器将为我们完成驴工作。 我们得到LazyInitializationException ,那么! 我们将以“视图”模式使用“打开实体管理器”,并消除此愚蠢的异常!
休息一下! 你不认为这是一个死胡同吗? –现在该改变一些东西了。 您可以在项目中使用复杂的方法,例如CQRS ,以及JPA中已经存在的可能性,这些方法可以帮助您更改本文中我描述的不良方式。
甜点的几个链接:
- CQRS信息
- 马丁·福勒(Martin Fowler)关于CQRS的文章
翻译自: https://www.javacodegeeks.com/2013/05/jpa-should-i-become-a-laziness-extremist.html