Probably my biggest gripe about using JPA (Hibernate) is the poor support for interfaces. A lot of people think that the ‘interfaces are a drag in ORM‘ is a silly argument because we are talking about entities and those tend to be tied to some concrete underpinnings anyway. But role classes are a different case.
Let‘s take a simple example from commerce: you login to a website, you are a User. We let you browse around and do things on the site and you may or may not want to buy something. Of course, we have a User class. First question: once we need to store a payment mechanism for you, would it go in User? Role classes would dictate that you have a class called Customer and the commerce-oriented parts of the app only know that interface. The simplest rule is ‘would I ever want a User that did not have PaymentMechanisms?‘ Of course the answer is yes.
But there is no easy way to do that in Hibernate. You can make Customer extend User, which is not a bad idea, it just means that you are going to have to have some logic to inject the proper instance into the appropriate contexts, performing additional lookups as needed.
So for example, you logged in, I got back a User and am holding that in a session-scoped bean. Now you want to go buy something. If my controller needs a Customer, all I have to do is go look that up, based on the User information I already have. In Java EE 6, it‘s pretty simple to make a Produces method in a factory somewhere that will simply have the User injected and then will load the Customer with the same ID and return it. It seems a tad hokey (like Superman going into the phone booth), but it makes sense. It‘s not that this cannot be done in 5: you can make a factory and simply outject it (if you are using Seam). But the @Produces seems like a cleaner, more above board solution.
One of the main reasons for role classes is access control, but they also provide a means of stemming the tide of complexity sprawl. Entities can get gunked up just like other classes, and then all future interactions have to wade through the clutter to figure out if there is some easy way to get what they need.
Maybe the interface only solution is a mirage. If we were not constrained by ORM requirements, we could use just interfaces to pull together the various potential roles. But since those interfaces don‘t really front any state per se, the reality is that the single underlying entity ends up pretty monolithic and the benefits of limiting exposure go out the window if there comes a reason to actually make changes to the underlying behemoth. Let‘s face it, that hardly ever ends up being the case. It‘s kind of like the caching calc where you are looking for the items that will have the highest read to write ratios. In programming, those are generally still a precious few. That said, I have been on a lot of really large projects where the domain model seemed to be the most stable part of the codebase. I do think that if role interoperability throughout the app can be leveraged fairly easily, it would be a feather in the cap of the whole dependency injection ideal: to transparently recompose complex contexts as needed.