@Transactional is primarily to ensure that a database operation functions as an atomic
unit, instead of possibly losing sync between tables when you do multiple operations in series.
What is more important here is whether the Entities in question are
attached or
detached.
An attached Entity object has an invisible connection to an EntityManager. Application code cannot see it, but the code weaver that makes JPA possible naintains and uses it.
A detached Entity lacks that connection and it's basically just the what-you-see-is-what-you get POJO.
You do not need to worry much about eager/lazy fetch for an attached object. If you want the associated roles for a user, just use the "getRoles()" method to obtain the User's Role collection and start accessing elements in that collection. If the Roles haven't already been fetched (and possibly cached, they will nonetheless be fetched when you access them.
A detached User, on the other hand, has to worry about eager/lazy fetch. Since it has no connection to the database, attempting to fetch the roles property will return the roles collection IF you did an eager fetch OR manually accessed it before detaching. However if you did NOT do one of the preceeding, you'll get back a proxy collection object that stands in for the roles and accessing it will throw an Exception.
On the whole, I recommend spending as much time detached as possible. If you are attached, it's very easy to push unintended changes to the database and you may be holding locks that degrade performance. On the other hand, if you make changes to detached objects, you have to re-attach them before they can be persisted. And one thing that's very important to note is that re-attaching an object does not simply modify the original detached object, it creates a whole new attached copy. That is, the object returned from a JPA merge() satisfies the "equals()" method, but not the "==" operation. Once merged, you should discard the pre-merge (detached) objects and work with the merged (attached) ones.
In most of my JPA apps, I have 3 persistence layers. The lowest defines the Entity objects. The next level up are the DAO's for those objects, where each DAO does find/CRUD opeations for one and only one table (or if tightly-bound, parent/child table set).
The next level up is the persistent object service level. This level works with sets of related objects. What I refer to as "working sets". They can retrieve a network of objects required for a business function as a detached set of objects. They can also accept a detached network of objects (working set), re-attach them, and invoke the necessary DAOs. Application code never invokes DAOs directly nor works with attached Entities. Service methods are all @Transactional, and it makes for a very tidy organization.