Search code examples
javajpaexceptionentitymanager

EntityManager not finding reference acts differently in try catch if calling println


I have an endpoint that looks like this:

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteScooter(@PathVariable long id) {
    boolean isDeleted = scootersRepository.deleteById(id);
    if (!isDeleted) throw new ResourceNotFoundException("The scooter could not be found with id: " + id);
    return ResponseEntity.ok().build();
}

And the relevant deleteById method:

@Transactional
@Override
public boolean deleteById(long id) {
    boolean isDeleted = false;
    try {
        Scooter scooterRef = entityManager.getReference(Scooter.class, id);
        System.out.println(scooterRef); // <--- this line here
        entityManager.remove(scooterRef);
        isDeleted = true;
    } catch (Exception e) {
        // no-op
    }
    return isDeleted;
}

If I leave the code like it is shown above and make a call to the delete endpoint passing in an unknown id this will throw a resourceNotFoundException (expected behaviour, all good so far)

But if I remove this specific line from the deleteById method:

System.out.println(scooterRef); // <--- this line here

An internalServerErrorException is thrown instead.

My question is, what exactly is this println invocation doing? And is there a cleaner solution to execute the expected behaviour of this code without using a println?


UPDATE:

The expected behaviour also occurs if I remove the println and try to access one of the attributes inside the reference, like so:

// System.out.println(scooterRef);
scooterRef.getMileage(); // <-- ResourceNotFoundException is thrown, good

Now I do vaguely remember that in some cases you need to access the referenced object in some way (e.g. by calling an attribute) to make it load completely or something like that, but I dont remember the exact reasoning anymore.


Solution

  • You can try using entityManager.find(Scooter.class, id);

    However from what this blog explains even though getReference only returns a proxy object, for deletion it should work exactly the same.