JavaFX 2 with JPA 2 and Drag and Drop – Part 2

In the first part of this series I gave an over view of the project and how to install and run it. Now I’ll cover the JPA aspects of the project.

Persistence is CRUD (Create, Read, Update, Delete)! Getting your objects in and out of a database is, for the most part, dull so if you can do it with the minimum of fuss you are winning from a development point of view. If you combine a sprinkle of generics with dose of JPA it turns out you can perform most of the basic CRUD tasks in an abstract base class leaving you more time to concentrate on the interesting bits of development.

Generally I’ll write a persistence service class for each entity class. The name of the service class will have the format “EntityNameService” e.g. the service class for the Person class is PersonService. This service class will extend the AbstractService class which implements the Service interface. The service interface is shown below, it simply defines methods that will handle the basic CRUD operations for a given entity type.

public interface Service<T extends Serializable> {
	T find(Long id);
	void remove(T item);
	void persist(T item);
	T merge(T item);
}

The AbstractService class than implements the remove, persis and merge methods of this interface and is shown below.

public abstract class AbstractService<T extends Serializable> implements Service<T> {
	protected EntityManagerFactory emf;
	public AbstractService(String persistenceUnitName) throws IOException {
		emf = PersistenceUtilities.getInstance().getEntityManagerFactory(persistenceUnitName, null);
	}
	@Override
	public void remove(T item) {
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		em.remove(em.merge(item));
		em.getTransaction().commit();
		em.close();
	}
	@Override
	public void persist(T item) {
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		em.persist(item);
		em.getTransaction().commit();
		em.close();
	}
	@Override
	public T merge(T item) {
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		T merged = em.merge(item);
		em.getTransaction().commit();
		em.close();
		return merged;
	}
}

Notice that the find method isn’t implemented. Since generics are implemented via type erasure in Java the type doesn’t exist at this point so “T.class” which is what you would need to use in the find method doesn’t make any sense. The find method is only a couple of lines of code though so it’s not a problem to stick it in the concrete class.

Finally with have the concrete service classes such as PersonService.

public class PersonService extends AbstractService<Person> {
	public PersonService(String persistenceUnitName) throws IOException {
		super(persistenceUnitName);
	}
	@Override
	public Person find(Long id) {
		EntityManager em = emf.createEntityManager();
		return em.find(Person.class, id);
	}
	public List<Person> findAll() {
		EntityManager em = emf.createEntityManager();
		Query q = em.createNamedQuery(Person.FIND_ALL);
		List<Person> results = q.getResultList();
		return results;
	}
	public List<Person> findUnassigned() {
		EntityManager em = emf.createEntityManager();
		Query q = em.createNamedQuery(Person.FIND_UNASSIGNED);
		List<Person> results = q.getResultList();
		return results;
	}
	public void deleteAll() {
		EntityManager em = emf.createEntityManager();
		Query q = em.createNamedQuery(Person.DELETE_ALL);
		em.getTransaction().begin();
		q.executeUpdate();
		em.getTransaction().commit();
	}
}

As mentioned above this class implements the find method plus a few other useful persistence operations that are specific to Person objects such as finding unassigned people and deleting all the people in the database.

One of the things I particularly like about this set up for persistence services is the ease of acquiring an EntityManager. The AbstractService holds an instance of the EntityManagerFactory which can spawn an EntityManager as required. The EntityManagerFactory is in turn set up and managed by a class called PersistenceUtilities as shown below.

public final class PersistenceUtilities {
	private static volatile PersistenceUtilities instance;
	private Map<String, EntityManagerFactory> emfMap = new HashMap<>();
	private PersistenceUtilities() {
	}
	public static PersistenceUtilities getInstance() {
		//double-checked lock - safe from Java 5 onwards.
		if (instance == null) {
			synchronized (PersistenceUtilities.class) {
				if (instance == null) {
					instance = new PersistenceUtilities();
				}
			}
		}
		return instance;
	}
	public boolean isConfigured(String persistenceUnitName) {
		return emfMap.containsKey(persistenceUnitName);
	}
	public EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, Map<String, String> emfSettings) {
		if (emfMap.get(persistenceUnitName) == null) {
			synchronized (this) {
				if (emfMap.get(persistenceUnitName) == null) {
					EntityManagerFactory emf = null;
					if (emfSettings == null) {
						emf = Persistence.createEntityManagerFactory(persistenceUnitName);
					} else {
						emf = Persistence.createEntityManagerFactory(persistenceUnitName, emfSettings);
					}
					emfMap.put(persistenceUnitName, emf);
				}
			}
		}
		return emfMap.get(persistenceUnitName);
	}
}

The PersistanceUtilities class is a singleton that holds a map of EntityManagerFactory objects based on their persistence unit name as defined in the persistence.xml file. The interesting method in this class is getEntityManagerFactory which actually handles the creation of the EntityManagerFactory instance and storing them in the map. The method optionally accepts a map of settings that are used to create the EntityManagerFactory – this is useful when you want to pass in a user name and password at start up rather than hold them in the persistence.xml file.

What all the above goodness means is that when the JavaFX controller class needs to use persistence services all that is needed is a single line to create the service class such as this:

personService = new PersonService(Demo.PERSISTENCE_UNIT_NAME);

I typically define the name of the persistence unit in the main class but you could, of course, set this as a parameter if needed.

The demo application defines two entities, Person and Department and both are pure POJO’s with annotation to support persistence. From the JavaFX point of view this makes them a little trickier to work with as JavaFX relies heavily on binding but IMHO it’s more important that you get your data model right than make your front end easy to code. As you will see from the demo it turns out that this isn’t a terribly big problem and there are ways around all the issues.

Posted in JavaFX and tagged , , , .

Leave a Reply

Your email address will not be published. Required fields are marked *