Aesis Aesis - 2 months ago 11
Java Question

Why is Hibernate querying twice?

While testing implementation of JPA into Spring I found out that my query is querying twice instead of once.

@Data
@Entity
@Table(name = "superfan_star")
public class Star implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(nullable = false)
private int id;
private String name;
private String nickname;
private String description;
private String thumbnail;
private String backgroundImage;
private Date created;
private Date updated;

@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "starId", referencedColumnName = "id", insertable = false, updatable = false)
private Set<Media> medias;
}


This is model class.

@Service
public class SuperfanStarService
{
@Autowired
private StarRepository starRepository;

@PersistenceContext
private EntityManager em;

@Transactional
public List<Star> getStars()
{
QStar qStar = QStar.star;
QMedia qMedia = QMedia.media;

List<Star> stars =
new JPAQuery(em)
.from(qStar)
.where(qStar.id.eq(19))
.list(qStar);

return stars;
}
}


This is my service class.

20160915 20:52:59.119 [http-nio-8080-exec-1] DEBUG j.sqlonly - org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)
9. select star0_.id as id1_2_, star0_.background_image as backgrou2_2_, star0_.created as created3_2_, star0_.description as descript4_2_, star0_.name as name5_2_, star0_.nickname as nickname6_2_, star0_.thumbnail as thumbnai7_2_, star0_.updated as updated8_2_ from superfan_star star0_ inner join superfan_media medias1_ on star0_.id=medias1_.star_id where star0_.id=19

20160915 20:52:59.173 [http-nio-8080-exec-1] DEBUG j.sqlonly - org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)
9. select medias0_.star_id as star_id11_2_0_, medias0_.id as id1_1_0_, medias0_.id as id1_1_1_, medias0_.created as created2_1_1_, medias0_.description as descript3_1_1_, medias0_.end_time as end_time4_1_1_, medias0_.is_approve as is_appro5_1_1_, medias0_.is_approved_final as is_appro6_1_1_, medias0_.is_pushed as is_pushe7_1_1_, medias0_.is_represent as is_repre8_1_1_, medias0_.length as length9_1_1_, medias0_.released as release10_1_1_, medias0_.star_id as star_id11_1_1_, medias0_.teleport_media_id as telepor12_1_1_, medias0_.thumbnail as thumbna13_1_1_, medias0_.title as title14_1_1_, medias0_.work_end as work_en15_1_1_, medias0_.work_start as work_st16_1_1_, medias0_.youtube_id as youtube17_1_1_, medias0_.youtube_title as youtube18_1_1_ from superfan_media medias0_ where medias0_.star_id=19


As you can see, it's querying twice instead of once, probably because of inverse update? Is there any way to make my JPA model query only once?

Thanks.

Answer

This works as expected. The first query gets the Star entity with id = 19 from the database, and the second query gets the linked Media entities for that Star entity from the database. (Carefully look at the log of the SQL statements to understand what is being queried).

Note that you specified FetchType.EAGER on the medias field in class Star:

@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "starId", referencedColumnName = "id", insertable = false, updatable = false)
private Set<Media> medias;

Eager fetching means that when you do a query for one or more Star objects, Hibernate immediately gets the linked Media objects - as opposed to lazy fetching, which means that the second query will not be done immediately, but only when necessary (when you access the medias member variable).

Comments