平均而言,执行查询、检索结果并将其映射到100个Book实体需要2ms。如果包含事务处理,则为2.89ms。对于小型且不那么新的笔记本电脑来说也不错。
Transaction: total 2890 per iteration 2.89 Query: total 2000 per iteration 2.0 3.3.默认FetchType对To-One关联的影响当我向你展示Book实体时,我指出我将FetchType设置为LAZY以避免其他查询。默认情况下,To-one关联的FetchtType是EAGER,它告诉Hibernate立即初始化关联。
这需要额外的查询,如果你的查询选择多个实体,则会产生巨大的性能影响。让我们更改Book实体以使用默认的FetchType并执行相同的测试。
@Entity public class Book { @ManyToOne @JoinColumn(name = "fk_author") private Author author; ... }这个小小的变化使测试用例的执行时间增加了两倍多。现在花了7.797ms执行查询并映射结果,而不是2毫秒。每笔交易的时间上升到8.681毫秒而不是2.89毫秒。
Transaction: total 8681 per iteration 8.681 Query: total 7797 per iteration 7.797因此,最好确保To-one关联设置FetchType为LAZY。
3.4.选择@Immutable实体Joao Charnet在评论中告诉我要在测试中添加一个不可变的实体(Immutable Entity)。有趣的问题是:返回使用@Immutable注解的实体,查询性能会更好吗?
Hibernate不必对这些实体执行任何脏检查,因为它们是不可变的。这可能会带来更好的表现。所以,让我们试一试。
我在测试中添加了以下ImmutableBook实体。
@Entity @Table(name = "book") @Immutable public class ImmutableBook { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", updatable = false, nullable = false) private Long id; @Version private int version; private String title; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "fk_author") private Author author; ... }它是Book实体的副本,带有2个附加注解。@Immutable注解告诉Hibernate,这个实体是不可变得。并且@Table(name =“book”)将实体映射到book表。因此,我们可以使用与以前相同的数据运行相同的测试。
long timeTx = 0; long timeQuery = 0; long iterations = 1000; // Perform 1000 iterations for (int i = 0; i < iterations; i++) { EntityManager em = emf.createEntityManager(); long startTx = System.currentTimeMillis(); em.getTransaction().begin(); // Execute Query long startQuery = System.currentTimeMillis(); List<Book> books = em.createQuery("SELECT b FROM ImmutableBook b") .getResultList(); long endQuery = System.currentTimeMillis(); timeQuery += endQuery - startQuery; em.getTransaction().commit(); long endTx = System.currentTimeMillis(); em.close(); timeTx += endTx - startTx; } System.out.println("Transaction: total " + timeTx + " per iteration " + timeTx / (double)iterations); System.out.println("Query: total " + timeQuery + " per iteration " + timeQuery / (double)iterations);有趣的是,实体是否是不可变的,对查询没有任何区别。测量的事务和查询的平均执行时间几乎与先前的测试相同。
Transaction: total 2879 per iteration 2.879 Query: total 2047 per iteration 2.047 3.5.使用QueryHints.HINT_READONLY查询EntityAndrew Bourgeois建议在测试中包含只读查询。所以,请看这里。
此测试使用我在文章开头向你展示的Book实体。但它需要测试用例进行修改。