何时使用Entity或DTO (2)

平均而言,执行查询、检索结果并将其映射到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查询Entity

Andrew Bourgeois建议在测试中包含只读查询。所以,请看这里。

此测试使用我在文章开头向你展示的Book实体。但它需要测试用例进行修改。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyxgx.html