Originally LAMS was written using Hibernate xml files (.hbm.xml) but with LDEV-4696 we switched to Hibernate 5.3 and annotated the Java beans used for Hibernate. These notes will help you if you are fixing bugs related to these changes or when creating new tools.
These instructions were written for Wildfly 14.
This are not supported by Hibernate 5.3. At runtime, when the query is executed you will get the error "Legacy-style query parameters (`?`) are no longer supported; use JPA-style ordinal parameters (e.g., `?1`) instead".
- If the calling method uses doFind(), then leave the HQL code using "?". The doFind method will change the "?" to P1, P2, P3, etc and generate matching named parameters P1, P2, P3, etc and fix it for you.
- If not using doFind(), change the HQL/SQL to use meaningful named parameters.
Suggested package structure:
org.lamsfoundation.lams.tool.<toolname> : Constants, applicationContent.xml
org.lamsfoundation.lams.tool.<toolname>.model : Hibernate related POJOs in a "model" package.
Note: Remove any service proxy class if they exists.
Using a model directory is very important for tools - the Hibernate Annotations scan in commonContext.xml is set up for "org.lamsfoundation.lams.tool.**.model" so if your annotated classes are in a different package, they will not be mapped with Hibernate.
Ensure the following path is on the project build classpath (or the newer version that matches whatever is in your Wildfly directories).
Note: hibernate-core-5.3.6.Final.jar is included in the build via lams_build/lib and in 3rd Party Libraries at the moment so we are doubling up, but once we've updated all the projects we can drop it from there and just use the project classpaths to access the jars directly from Wildfly.
When you are importing the classes needed for the annotations, select the javax.persistence.* ones, not the Hibernate ones - apart from cascade="save-update" (see later). You will need the use the Hibernate GenericGenerator import (and this is why you need hibernate-core-5.3.6.Final.jar in your build path).
If you find any 2nd level cache tags ( <cache usage="transactional" />) just ignore them. Do not add cache annotations. We will revisit the caching when we have it enabled and will do it in the appropriate JPA way then.
If the object is the root of an inheritance hierachy then add
Then in the subclass add the Discriminator
Add a @Column annotations for all other persistent fields. Just use name and columnDefinition options. Name is required (and should be omitted) if the name of the field is identical to the name of the column. If you want to note anything special about the column use the columnDefinition option. The column definition and the other options (length, type, etc) are only for DDL so no point meticulously recording them all when we maintain the database manually - we just risk the definitions in the code getting out of sync with the database.
If the field is the DiscriminatorColumn (see above) then use:
Every non-static and non-transient property are assumed persistent so any temporary values (and some POJOs are used in the web layer) must be marked as @Transient.
If a collection is sorted, you need to use @OrderBy
In a one-to-many like content to session we have:
If you find a one-to-many with inverse = "false" (ie control is from the one side, not the many side) this may be implementable using a join column, rather than a mappedBy. For example, in Forum there is a link from the Message table back to itself, using the "authored_parent_uid" field.
- You do not need to specify "fetch = FetchType.LAZY" in @OneToMany relationship as it is the default, but you will need to define "fetch = FetchType.EAGER" if you come across a mapping with lazy="false".
- cascade="save-update" needs to be converted to Hibernate CascadeType.SAVE_UPDATE should be used instead of the JPA cascade.
If you find any <meta attribute="use-in-equals">true</meta>, <meta attribute="use-in-tostring">true</meta> entries and the class does not have a toString() or equals() method you can write methods based on these attributes. They are not converted to annotations.
If we want to use length, not null, etc validation at runtime we need to use HibernateValidator, which implements Bean Validation. Looking at all the examples and having a go at getting it running, Spring MVC is set up to use the Bean Validation, but the Hibernate ORM layer is not. Therefore we will leave this for now and revisit it as needed in the web layer.