What follows is not new. It is very well known by jboss+hibernate users and a lot of info can be found at jboss and hibernate forums. Anyway, it took me almost four hours to clean up the mess so I think it is suitable for this blog (for those who have not realized yet, this blog is mostly about my troubles in the java world). So here it goes:
I was trying to configure a many-to-many relation between documents and document bodies. Each document has a collection of bodies, where each body represents a different translation, so each body corresponds to a different language. Each body on the other hand can belong to many documents, thus making the relation many-to-many. On top of this configuration, I wanted to access the bodies of a document by their language id so the map-based solution seemed ok:
public class MyDocument {
...
@ManyToMany
@MapKey(name="langId")
private Map<Integer, MyDocumentBody> bodies;
...
}
The
bodies
Map is keyed by the integer language id.
Unfortunately, due to
this bug, hibernate generates illegal sql for Oracle, when trying to initialize the
bodies
Map. To be more specific, it uses a table alias in the FROM clause but it puts the "AS" keyword in front e.g.:
select * from TableA as a where blah, blah
The "as" is optional but acceptable by many databases. However it is not acceptable by Oracle, as it is explained in the links mentioned above. As I found
here the generation of "as" is due to a bug in annotations and the upgrade to hibernate-annotations 3.3.0.GA is suggested. However, the use of this version requires an upgrade of the hibernate-entity manager to version 3.3.x as the
compatibility matrix suggests. My troubles didn't end at this point though, because I was using jboss-4.0.5.GA whose EJB3-JPA support is not compatible with the new hibernate-entitymanager. The upgrade to 4.2.0.CR1 seemed inevitable (this has a better EJB3 support but the hibernate-* jars still needed upgrading). Alas, a
java.lang.NoClassDefFoundError: org/hibernate/annotations/common/reflection/ReflectionManager
was waiting for me during deployment. Another google search and
this finally solved my problem. hibernate-annotations-common.jar, which is not included in jboss by default, was needed in the lib folder. Four hours and a lot of googling later, I had my map-based many-to-many relation.