Although fetch type is lazy, hibernate for some reason sends the second request and fetches the lazy one. I have been dealing with this problem for a few days for some reason I don't understand. I tried some ways on the internet, but unfortunately I couldn't fix it, I would be very grateful if you could help me by looking at my code.
User Entity
@Entity
@Table(name = "users")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(name = "username", length = 50)
private String username;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_friends" , joinColumns = @JoinColumn(name = "user_id") , inverseJoinColumns = @JoinColumn(name = "friend_id"))
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<User> friends = new HashSet<>();
}
User Service
@Service
@Transactional
public class UserService implements ICrudService<User> {
@Autowired
private UserRepository repository;
@Override
@Transactional
public List<User> findAll() {
return repository.findAll();
}
@Override
@Transactional
public User findById(Long id) throws Exception {
return repository.findById(id).orElseThrow(() -> new Exception("Kullanici Bulunamadi"));
}
@Override
@Transactional
public User create(User user) {
return repository.save(user);
}
@Override
public void delete(Long id) {
repository.deleteById(id);
}
}
User Controller
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/all")
public List<User> getUsers(){
return userService.findAll();
}
@GetMapping("/{userId}")
public User getUserById(@PathVariable Long userId) throws Exception {
return userService.findById(userId);
}
@PostMapping
public User saveUser(@RequestBody User user){
return userService.create(user);
}
@DeleteMapping("/{userId}")
public void deleteUserById(@PathVariable Long userId){
userService.delete(userId);
}
}
I use JpaReository as repository in service
And the output of "/users/all" looks like this
Output
[
{
"id": 1,
"username": "testUser",
"email": "test@gmail.com",
"password": "verystrongpasword",
"friends": []
}
]
This is the hibernate sql format
Hibernate:
select
u1_0.id,
u1_0.email,
u1_0.password,
u1_0.username
from
users u1_0
Hibernate:
select
f1_0.user_id,
f1_1.id,
f1_1.email,
f1_1.password,
f1_1.username
from
user_friends f1_0
join
users f1_1
on f1_1.id=f1_0.friend_id
where
f1_0.user_id=?
When fetch type for property is Lazy
, the data is retrieved on demand - when the getter for the property is invoked. User
is serialized as json when the response is sent, and json libraries normaly to this using the getters - getFriends()
is invoked reflectively by the underlying library.
The solution (and good practice) is to use a DTO
for response/request, not entities.