其他分享
首页 > 其他分享> > Hibernate5 与 Spring Boot2 最佳性能实践(2)

Hibernate5 与 Spring Boot2 最佳性能实践(2)

作者:互联网

[上一篇][1]介绍了 Hibernate 5 和 Spring Boot 2 一些性能方面的最佳实践,这一篇会继续介绍剩下的内容。让我们开始吧!


[26. 如何通过 SqlResultSetMapping & NamedNativeQuery 提取 DTO][2]

[27. 如何通过 javax.persistence.Tuple 和原生 SQL 提取 DTO][3]

[28. 如何通过 javax.persistence.Tuple 和 JPQL 提取 DTO][4]

[29. 如何通过 Constructor 表达式和 JPQL 提取 DTO][5]

[30. 如何通过 ResultTransformer 和原生 SQL 提取 DTO][6]

[31. 如何通过 ResultTransformer 和 JPQL 提取 DTO][7]


[1]:https://dzone.com/articles/50-best-performance-practices-for-hibernate-5-amp

[2]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoSqlResultSetMappingAndNamedNativeQuery

[3]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoTupleAndSql

[4]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoTupleAndJpql

[5]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoConstructorExpression

[6]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoResultTransformer

[7]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoResultTransformerJpql


32. 通过 Blaze-Persistence 实体视图实现 DTO


"描述:" 获取不必要的数据很容易造成性能损失,使用 DTO 允许只提取必须的数据。在这个示例中,使用了 Blaze-Persistence 实体视图。


技术要点



[示例代码][8]


[8]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoBlazeEntityView


33. 没有 @OrderColumn 时使用 @ElementCollection 的执行效果


没有 `@OrderColumn` 时,对 `@ElementCollection` 进行插入和删除会造成性能损失。有 `@OrderColumn` 时,情况会好一些。


"描述:"在这个示例中,展示了没有 `@OrderColumn` 时使用 `@ElementCollection` 可能带来的性能损失。接下来的示例(例34)加上 `@OrderColumn` 能减少性能损失。


技术要点



示例输出


图片


[示例代码][9]


[9]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootElementCollectionNoOrderColumn


34. 使用 OrderColumn 时 @ElementCollection 的执行效果


没有 `@OrderColumn` 时,对 `@ElementCollection` 进行插入和删除会造成性能损失。有 `@OrderColumn` 时,情况会好一些。


"描述:"在这个示例中,展示了没有 `@OrderColumn` 时使用 `@ElementCollection` 可能带来的性能损失。加上 `@OrderColumn` 后,能减少对集合尾部操作(例如,在集合尾部执行 add/remove 操作)的性能损失。主要原因是操作对象左边的元素都不会移动,性能开销主要集中在集合尾部。


技术要点



示例输出


图片


[示例代码][10]


[10]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootElementCollectionWithOrderColumn


35. 如何避免 Open Session In View 反模式带来的延迟加载实体问题(1 Session/1 HTTP Request-Response)


只要存在延迟加载实体,无论将来是否用到 Open-Session In View 都会获取,从而造成严重的性能问题。


"描述:"Spring Boot 会默认开启 Open Session In View 反模式。如果确实需要使用,最好能够减少由此带来的性能损失。一种优化方法,可以把 `Connection` 标记为只读,这样能够避免数据库服务器记录事务日志。另一种办法,对那些不希望被延迟加载的实体属性显式标记。


技术要点



>>>

“注意:该 filter 默认不会刷新 Hibernate Session,刷新模式默认设为 `FlushMode.NEVER`。这里假定 Service 层事务会处理刷新:在事务读写期间,活动事务管理器会临时把刷新模式更改为 `FlushMode.AUTO`,事务结束时重置刷新模式为 `FlushMode.NEVER`。如果需要在不使用事务的情况下使用 filter,可以考虑修改 `flushMode` 更改默认刷新模式。”

>>>


示例输出



示例代码][11]


[11]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootSuppressLazyInitInOpenSessionInView


36. 如何使用 Spring Projection(DTO) 和 Inner Join


SQL JOIN 和 DTO 有助于解决 N+1 问题,例36至42包含了很多相关示例。


> 译注:“N+1 问题”即执行一次查询 N 条主数据后,由于关联引起的 N 次从数据查询,因此会带来了性能问题。一般来说,通过延迟加载可以部分缓解 N+1 带来的性能问题。


"描述:"这个示例使用 JPQL 和原生 SQL(MySQL)验证 Spring Projection(DTO) 和 Inner Join 方案。


技术要点



[示例代码][12]


[12]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoViaInnerJoins


你可能也会对下面内容感兴趣


[37. 如何使用 Spring Projections(DTO) 和 Left Join][13]

[38. 如何使用 Spring Projections(DTO) 和 Right Join][14]

[39. 如何使用 Spring Projections(DTO) 和 Full Join][15]

[40. 如何使用 Spring Projections(DTO) 和 Left Excluding Join][16]

[41. 如何使用 Spring Projections(DTO) 和 Right Excluding Join][17]

[42. 如何使用 Spring Projections(DTO) 和 Outer Excluding Join][18]


[13]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoViaLeftJoins

[14]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoViaRightJoins

[15]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoViaFullJoins

[16]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoViaLeftExcludingJoins

[17]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoViaRightExcludingJoins

[18]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoViaOuterExcludingJoins


43. 如何使用 Spring Post 提交


本例中描述的现象通常出现在生产环境,这种环境的负载很高。Spring post-commit hook 会在执行完成前让数据库连接保持打开状态。提交结束后,在 hook 函数中执行耗时任务。高负载时会导致连接池处于饥饿状态。显然,这种情况下需要更长时间才能连接成功。


"描述:"在这个示例展示了 Spring Post Commit Hook.


技术要点



[示例代码][19]


[19]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootPostCommit


44. 如何在无关实体上使用 Spring Projection(DTO) 和 Join(Hibernate 5.1+)

Hibernate 5.1 引入了 Explicit Join 可以在无关实体上使用,语法和执行效果与 SQL JOIN 类似。


"描述:" 在这个示例展示了 Spring Projection 和无关实体连接。Hibernate 5.1 引入了 Explicit Join 可以在无关实体上使用,语法和执行效果与 SQL JOIN 类似。


技术要点



[示例代码][20]


[20]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDtoUnrelatedEntities


45. 为什么要避免在实体上使用 Lombok @EqualsAndHashCode


Lombok 时目前非常流行的一个开发库。但请注意,在实体上使用 Lombok `@EqualsAndHashCode` 可能会造成严重问题。


"描述:"实体必须像[下面][21]这样实现 `equals()` and `hashCode()`,而且必须在 *transient*、*attached*、*detached* 和 *removed* 状态转换中保持 equal。Lombok `@EqualsAndHashCode` 无法满足上述要求。


[21]:https://vladmihalcea.com/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/


技术要点


"避免"



"推荐"



`equals()` 和 `hashCode()` 的优秀实现:


图片


[示例代码][22]


[22]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootLombokEqualsAndHashCode


46. 如何通过 JOIN FETCH 避免 LazyInitializationException


如果你从未遇到 `famousLazyInitializationException`,说明你从未用过 Hibernate :) 加入从 `LAZY` 转为 `EAGER` 解决了这个异常,这个例子就是为你准备的。


"描述:" 当遇到 `LazyInitializationException` 时,通常会把获取类型从 `LAZY` 改为 `EAGER`。这是一种很糟糕的[代码异味][23]。避免这种异常的最好办法是 `JOIN FETCH` + DTO(如果有需要)。这个示例展示了无 DTO 的 JOIN FETCH,通过单个 `SELECT` 查询获取实体。但是,基于上述 DTO 示例也可以很方便地改为使用 DTO。


[23]:https://vladmihalcea.com/eager-fetching-is-a-code-smell/


技术要点



示例输出


图片


[示例代码][24]


[24]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootJoinFetch


47. 如何合并实体集合


如何正确地合并集合不是一件轻松的事情!


"描述:"这个 Spring Boot 示例基于[这篇文章][25]。这是 Vlad 例子的一个函数式实现。'强烈推荐阅读此文'


[25]:https://vladmihalcea.com/merge-entity-collections-jpa-hibernate/


技术要点



[示例代码][26]


[26]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootMergeCollections


48. 如何根据需要延迟获取数据库连接(Hibernate 5.2.10)


得到数据库连接后不立即使用可能导致性能下降。需要数据库连接的人可不会一直等待。


"描述:" 这个 Spring Boot 示例展示了如何利用 Hibernate 5.2.10 特性根据需要延迟获取连接。通常,调用 `@Transactional` 注解的方法后会立即得到连接。假如这个方法在执行第一条 SQL 语句后包含了一些耗时的任务,那么就会毫无意义地一直保持连接。但是,Hibernate 5.2.10 允许根据需要延迟获取连接。示例采用 HikariCP 作为 Spring Boot 默认连接池。


技术要点



示例输出


图片


[示例代码][27]


[27]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootDelayConnection


49. 如何通过 Hibernate hi/lo 算法获取主键


通常,我们不太关心如何生成或获取主键。如果真正关注的话,会考虑使用 `SEQUENCE` 这种便捷、灵活且高效的方法。然而,每个 sequence 都会执行一个数据库行程导致性能问题。hi/lo 是一种标识符序列生成优化算法。


"描述:" 这个 Spring Boot 示例使用 hi/lo 算法,在10个数据库行程中,批量执行1000次插入(每次10条记录)并获取1000个主键。


技术要点



示例输出


图片


[示例代码][28]


[28]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootHiLo


50. 如何编写高效双向 @ManyToMany 关联


你是否需要一个“多对多”关系的数据表,而且不希望使用两个 `@OneToMany` 关联进行映射?如果你更喜欢 `@ManyToMany` 双向关联,可以变得更高效一点。


"描述:" 这个示例是一个关于如何编写高效双向 `@ManyToMany` 关联的验证


技术要点



示例输出


图片


[示例代码][29]


[29]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootManyToManyBidirectional


51. 在 @ManyToMany 关系中优先使用 Set 而非 List


在 `@ManyToMany` 中使用 `List` 而不是 `Set` 可能会生成比预期更多的 SQL,例如删除操作。从而导致降低下降。


"描述:"这个 Spring Boot 示例,在双向 `@ManyToMany` 关系中分别使用了 `List` 与 `Set` 删除记录。结论是 `Set` 效果更好,该结论对于单项关系也成立。


技术要点



示例输出


图片


[示例代码][30]


[30]:https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/HibernateSpringBootManyToManyBidirectionalListVsSet


如果喜欢本文,你可能也会对[这本书][31]感兴趣。


[31]:https://leanpub.com/java-persistence-performance-illustrated-guide


标签:Hibernate5,Hibernate,SpringBoot,示例,Spring,Boot2,github,https,com
来源: https://blog.51cto.com/u_15127686/2832717