4
votes

I have an entity named User which has the following field called roles:

@ManyToMany
@JoinTable(
        name = "user_role",
        joinColumns = {@JoinColumn(name = "user_id", nullable = false)},
        inverseJoinColumns = {@JoinColumn(name = "role_id", nullable = false)}
)
private List<Role> roles;

I load the User via the use of a service method and the service method is wrapped in a transaction (JTA). After calling the service method and retrieving the User, I access this role field outside of the transaction that was used to load the User entity. I was expecting to get an error because the eclipselink documentation states that, by default, the fechtype for a ManyToMany association is lazy. This tells me that when the User entity was loaded in the service method, the roles should not be automatically loaded.

Why was I able to access the roles outside of the transaction? Why does it seem like the roles were fetched eagerly instead of lazy?

Here is the service class which loads the user (I've removed some code not relevant to the question):

@Service
@Transactional(rollbackFor = ServiceException.class)
public class UserServiceImpl implements UserService {

    @Autowired(required = true)
    private UserRepository userRepository;


    @Override
    public User authenticate(String username, String password) throws ServiceException {
        //Get the user
        List<User> users = userRepository.findByUsername(username);

        if (users == null || users.isEmpty() || users.size() > 1) {
            return null;
        }

        User user = users.get(0);
        String hash = getHash(password, user.getSalt());

        return StringUtils.equals(hash, user.getPassword()) ? user : null;
    }
}
1
Could we see the code where the User is loaded?Pablo

1 Answers

5
votes

EclipseLink allows fetching lazy relationships as long as the context is still available as described here: https://forums.oracle.com/forums/thread.jspa?messageID=1706796

Link is dead and I can't find the original post, but documentation has a one line on it under "Container Managed Persistence Contexts":

EclipseLink supports accessing an entity's LAZY relationships after the persistence context has been closed.

There have been a number of posts in this and other forms on the topic as it is a major differentiator from other JPA providers, as is its shared cache implementation which the feature is closely tied to.