I have Entity class Employee :
@Entity
@NoArgsConstructor(force = true)
@AllArgsConstructor
@Builder
@Data
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(name = "employee_id")
private UUID employeeId;
@Column(name = "name")
@NonNull
private String name;
@Column(name = "surname")
@NonNull
private String surname;
@ManyToOne( cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@ManyToMany(mappedBy = "employees", cascade = CascadeType.ALL,fetch = FetchType.LAZY)
private Set<Equipment> tools;
@ManyToMany(mappedBy = "employees", cascade = CascadeType.ALL,fetch = FetchType.LAZY)
private Set<Training> trainings;
and User entity class
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@Table(name = "user_account")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(name = "user_id")
private UUID id;
@NotBlank
@Length(min =3)
@Column(name = "name")
private String name;
@NotBlank
@Length(min =6)
@Column(name = "password")
private String password;
@NotBlank
@Pattern(regexp = "^(.+)@(.+)$")
@Column(name = "email",unique = true)
private String email;
@OneToMany(mappedBy = "user")
private Set<Equipment> tools;
@OneToMany(mappedBy = "user")
private Set<Training> trainings;
@OneToMany(mappedBy = "user")
private Set<Employee> employees;
@OneToMany(mappedBy = "user")
private Set<Car> cars;
Service class:
@Transactional
public Employee getEmployee(UUID employeeUUID) {
return employeeRepository.findEmployeeByEmployeeId(employeeUUID).orElseThrow(() -> new EntityNotFoundException("Employee not found"));
}
Repository DAO
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, UUID> {
Optional<Employee> findEmployeeByEmployeeId(UUID employeeId);
}
While I am trying to return the Employee entity from database response time is 1 second
This is how the response looks like:
{
"employeeId": "935ad5a2-34cb-4b27-8706-7d07fc283c84",
"name": "2",
"surname": "2",
"user": {
"id": "694b1eb9-622b-4333-84d2-69e7e1f96a33",
"name": "Correct",
"password": "$2a$10$tb.5rVD0PGpU1P99tCtrJufz.ONZC8hg6D1fgjAkVyGDJQq92YeV.",
"email": "correct@correct.com",
"tools": [],
"trainings": [],
"employees": [],
"cars": [],
"enabled": true,
"username": "correct@correct.com",
"authorities": null,
"accountNonLocked": true,
"accountNonExpired": true,
"credentialsNonExpired": true
},
"tools": [],
"trainings": [
{
"trainingId": "065a1019-ebc9-406d-8c24-fcd77ca51054",
"name": "Training1",
"description": "Training",
"employees": [],
"user": {
"id": "694b1eb9-622b-4333-84d2-69e7e1f96a33",
"name": "Correct",
"password": "$2a$10$tb.5rVD0PGpU1P99tCtrJufz.ONZC8hg6D1fgjAkVyGDJQq92YeV.",
"email": "correct@correct.com",
"tools": [],
"trainings": [],
"employees": [],
"cars": [],
"enabled": true,
"username": "correct@correct.com",
"authorities": null,
"accountNonLocked": true,
"accountNonExpired": true,
"credentialsNonExpired": true
}
}
]
}
config:
spring:
jackson:
serialization:
fail-on-empty-beans: false
datasource:
url:
username:
password:
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: validate
show-sql: true
properties:
hibernate:
format_sql: true
database: postgresql
open-in-view: false
flyway:
baseline-on-migrate: true
myapp:
secretKey: ""
I was trying to map Employee to DTO class but it didn’t help.
@Transactional
public EmployeeDTO getEmployee(UUID employeeUUID) {
Employee employee = employeeRepository.findEmployeeByEmployeeId(employeeUUID)
.orElseThrow(() -> new EntityNotFoundException("Employee not found"));
return EmployeeDTO.builder()
.uuid(employee.getEmployeeId())
.name(employee.getName())
.surname(employee.getSurname())
.build();
}
even while using native query it keeps making too much queries and response doesnt change
@Query(value = "SELECT * FROM Employee WHERE employee_id= :employeeId",nativeQuery = true)
Optional<Employee> findEmployeeByEmployeeId(UUID employeeId);
I was trying different approaches with join fetch (but it seems useless because i want data from only one table)
@Query(value = "SELECT new com.example.EquipmentApi.dto.EmployeeDTO(e.employeeId, e.name, e.surname) FROM Employee e WHERE e.employeeId = :employeeId")
Optional\<EmployeeDTO\> findEmployeeByEmployeeId(@Param("employeeId") UUID employeeId);
Only thing which worked is returning DTO directly from repository. But I am not sure if this is a correct approach.
Why I get all information about user while I have fetch type lazy set in all entities ? Also i don’t use user in service class except @AuthenticationPrincipal User user
in controller class.
Is it normal behaviour for JPA/HIBERNATE to return all relations for entity while using lazy loading?
What can I do to reduce number of queries ? I got 200 hibernate queries in console (I have show-sql: true in properties)