I know there are many similar questions about this trouble but nothing works for me.
I have @ManyToOne relationship between Aim and User.
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", nullable = false, updatable = false)
private User user;
and
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private Collection<Aim> userAims;
respectively.
@Override
@Transactional(propagation = Propagation.REQUIRED)
@PreAuthorize("isAuthenticated() and principal.user.isEnabled() == true")
public Aim findById(String aimId) throws NumberFormatException, EntityNotFoundException {
Aim aim = null;
try {
aim = aimRepository.findOne(Long.parseLong(aimId));
} catch (NumberFormatException e) {
throw new InvalidDataAccessApiUsageException(e.getMessage(), e);
}
if (aim == null) throw new EntityNotFoundException("Aim with id: " + aimId + " not found!");
return aim;
}
@OneToMany associations work fine with lazy fetching. Method isn't nested to another @Transactional method so @Transactional works fine.
So the record exists.
Pay attention that I haven't the LazyInitException
Thanks in advance!
I'm guessing from the code in your findById
method, and by the reference to "lazy initialization not working" in the title, that you are wanting to find an Aim
object by it's numeric Id, along with the associated User
object.
In order to do this with lazy-loading, you need to 'get' the associated object, and (most importantly) you need to 'get' one of the associated entity's fields.
So the code inside the try
block should be:
aim = aimRepository.findOne(Long.parseLong(aimId));
if (aim != null && aim.getUser() != null) {
aim.getUser().getUserId(); // doesn't need to be assigned to anything
}
Alternatively, if you have a logger available you can use the userId
in a debug or trace log message:
if (aim != null && aim.getUser() != null) {
logger.debug("Lazy-loaded User " + aim.getUser().getUserId());
}
This has the added benefit that you can debug how things are lazy-loaded.
By the way, we found out the hard way that making a find routine throw an Exception when it doesn't find something is a bad idea. This is because you might want to use the find routine to find out if an Entity does NOT exist. If that is happening within a transaction, your exception may trigger an unwanted rollback (unless you specifically ignore it). Better to return null
and check for that instead of using a try ... catch
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With