Issue
I wrote a simple entity named "User" and another one called "Company". User entity has company inside with @ManyToOne(fetch = LAZY) mapping. When I create the session object and call get() method Hibernate executes select query and after it update, why?
User entity:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@ToString
@Builder
@Entity
@Table(name = "users")
public class User2 {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
@Column(unique = true)
private String username;
@Embedded
@EqualsAndHashCode.Exclude
private PersonalInfo personalInfo;
@Enumerated(STRING)
@EqualsAndHashCode.Exclude
private Role role;
@Type(JsonType.class)
@EqualsAndHashCode.Exclude
private String info;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "company_id")
@EqualsAndHashCode.Exclude
@ToString.Exclude
private Company company;
}
Company entity:
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
@ToString
@Builder
@Entity
public class Company {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
private String name;
}
Main:
public class HibernateEntityMappingRunner {
public static void main(String[] args) {
try (SessionFactory sessionFactory = buildSessionFactory();
Session session = sessionFactory.openSession()
) {
session.beginTransaction();
User2 user2 = session.get(User2.class, 2);
session.getTransaction().commit();
}
}
}
Hibernate console log:
Hibernate:
select
u1_0.id,
u1_0.company_id,
u1_0.info,
u1_0.birth_date,
u1_0.firstname,
u1_0.lastname,
u1_0.role,
u1_0.username
from
users u1_0
where
u1_0.id=?
Hibernate:
update
users
set
company_id=?,
info=?,
birth_date=?,
firstname=?,
lastname=?,
role=?,
username=?
where
id=?
Solution
See https://hibernate.org/community/contribute/intellij-idea/#debugging for details. The problem is that some of your toString()
implementations (which the IntelliJ debugger invokes) access state of uninitialized entity/collection proxies, which will cause lazy initialization and hence a select query. If you have pending flushes (insert/update/delete) which affect one of the tables that are about to be selected from, Hibernate forcefully executes pending flushes.
By changing your toString()
implementations or changing how IntelliJ shows objects in the debugger, you can avoid this.
Answered By - Christian Beikov
Answer Checked By - Terry (JavaFixing Volunteer)