Spring/Hibernate optimization: JPA with @OneToOne mapping

Lately I wanted to see how Hibernate actually construct sql statements. And it seems like it makes somtimes unnecessary joins. Those are my playground's results.

Repo: https://github.com/toficzak/social-app

Setup:
@Entity
@Table(name = "users")
public class User extends BaseEntity {
}
@Entity
public class Post extends BaseEntity {
@NotBlank
String message;
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id", referencedColumnName = "id")
User author;
}
view raw Classes.java hosted with ❤ by GitHub

Post repository consists of 3 methods:

@Repository
public interface PostRepository extends CrudRepository<Post, Long> {
Optional<Post> findTopByAuthorOrderByIdDesc(User author);
Optional<Post> findTopByAuthorIdOrderByIdDesc(Long authorId);
@Query("from Post where author_id = ?1 order by id desc")
Optional<Post> findWithCustomQueryOrderByIdDesc(Long authorId);
}

Sql generated by Hibernate:
--> By author id:
Hibernate:
select
post0_.id as id1_0_,
post0_.author_id as author_i3_0_,
post0_.message as message2_0_
from
post post0_
left outer join
users user1_
on post0_.author_id=user1_.id
where
user1_.id=?
order by
post0_.id desc limit ?
--> By author:
Hibernate:
select
post0_.id as id1_0_,
post0_.author_id as author_i3_0_,
post0_.message as message2_0_
from
post post0_
where
post0_.author_id=?
order by
post0_.id desc limit ?
--> With custom query:
Hibernate:
select
post0_.id as id1_0_,
post0_.author_id as author_i3_0_,
post0_.message as message2_0_
from
post post0_
where
author_id=?
order by
post0_.id desc
view raw Hibernate.sql hosted with ❤ by GitHub
How did I measure execution time:
startTime = System.nanoTime();
method();
endTime = System.nanoTime();
duration = (endTime - startTime);
results.add(duration);
average = results.stream().mapToLong(Long::longValue).average().getAsDouble()

  
Simple select measure

By author id: 1952090.938
By author (User provided): 1048579.671
By author (User not provided): 1021450.464
By custom query: 935087.347

My custom JPA query is the fastest option - it skips whole User join section. But why is it needed at all? Seems like an error in my design.

Komentarze

Popularne posty z tego bloga

Java EE 8 & Wildfly 17 & RestEasy setup

Optional finallyLearned()

Testing: jUnit's TemporaryFolder