Java Persistence API (JPA)

Enumeration collection assignment

The following example shows the required annotations to assign a collection of roles (defined as enum class)  to a user entity.

@Entity
@Table(name = "t_user")
public class User {

	@Id
	private String id;

	@ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
	@CollectionTable(name = "t_userrole", joinColumns = @JoinColumn(name = "userid"))
	@Column(name = "role", nullable = false)
	@Enumerated(EnumType.STRING)
	private Set<Role> roles = new TreeSet<Role>();

	...
}

Common JPA annotations

Use the annotation @Temporal to store java.util.Date fields into database.

@Entity
public class Journal extends Literature {

    @Temporal(TemporalType.DATE)
    private java.util.Date publicationDate;

    @Enumerated(EnumType.STRING)
    private PublicationType pubType;

}

JPQL Constructor Expressions

If you want to create DTOs on-the-fly without iterating your query result list you can use JPQL constructor expressions.

SELECT NEW com.patternbox.tangocalendar.location.application.data.LocationData(
    l.identifier, l.name, l.address.country, l.address.state, l.address.town, 
    l.address.postalCode, l.address.street) FROM Location l

Separating Query Logic

In order to separate database query logic from my domain model I annotated my JPA repositories with @NamedQueries. Unfortunately it does not work because JPA only parses classes that are mentioned in the persistence.xml configuration. Annotating the repository with @MappedSuperclass overcomes this problem.

Java-Class

@MappedSuperclass
@NamedQueries({
		@NamedQuery(name = "findAll", query = "...") })
public class JpaLiteratureRepository { 
	... 
}

persistence.xml

<persistence-unit name="LocationPU">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:jboss/datasources/TangocalendarDS</jta-data-source>
    <class>[...].JpaLiteratureRepository </class>
</persistence-unit>

OptimisticLockException

Concurrent write access to JPA Entity with optimistic locking might cause a OptimisticLockException wrapped in an EJBException. The following code checks whether at least one of the exception causes is instance of OptimisticLockException. Otherwise the orignal EJBException will be re-thrown.

private void checkOptimisticLockException(EJBException ex) {
	Throwable cause = ex;
	while(cause.getCause() != null) {
		cause = cause.getCause();
		if (cause instanceof OptimisticLockException) {
			return;
		}
	}

	throw ex;
}