CDI and JPA tutorial

User Rating: 4 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Inactive
 

One popular issue of every application is about handling multiple database resources (at minimum you should consider handling a production DB and a development DB). In this tutorial we will show how you can solve this elegantly with CDI and its powerful annotations.

JPA and CDI

Basically, CDI is an annotation-driven injection framework that minimizes the bulk of boilerplate code that developers have to write. It is designed to greatly increase productivity, testability, and the quality of business applications built on the Java platform.

Let's see an example taken from the KitchenSink example:

 @Inject
 private EntityManager em;

  public List<Member> findAllOrderedByName() {


        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Member> criteria = cb.createQuery(Member.class);
        Root<Member> member = criteria.from(Member.class);

        criteria.select(member).orderBy(cb.asc(member.get("name")));
        return em.createQuery(criteria).getResultList();
  }


Here we are injecting an EntityManager and use it to issue a Query. That's pretty fine, however let's see how we can improve this by adding your own custom EntityManager qualifier annotations, to return a specific EntityManager using standard CDI annotations:

The following Qualifier will be used by Producer methods to create a MySQLDatabase-bound Entity Manager:

package com.sample;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.inject.Qualifier;


@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface MySQLDatabase {
}


And here's the Producer class, which will be used to create Entity Managers which are bound to the "primary" Persistence Context

package com.sample;

import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;

public class DatabaseProducer {

    @Produces
    @PersistenceContext(unitName = "primary")
    @MySQLDatabase
    private EntityManager em;


}


Here's the sample persistence.xml file which contains two persistence unit: the first one which is bound to MySQL and the second one which uses the default ExampleDS DB.

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0"
   xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="primary">

      <jta-data-source>java:jboss/datasources/MySqlDS</jta-data-source>
       <properties>

         <property name="hibernate.hbm2ddl.auto" value="create-drop" />

      </properties>
   </persistence-unit>

      <persistence-unit name="secondary">

      <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
      <properties>
         <!-- Properties for Hibernate -->
         <property name="hibernate.hbm2ddl.auto" value="create-drop" />
         <property name="hibernate.show_sql" value="false" />
      </properties>
   </persistence-unit>
</persistence>


Now it's just a matter of adding the @MySQLDatabase database annotation to mark an EntityManager injection as bound to MySQL database:

@MySQLDatabase
@Inject
private EntityManager em;


You can create of course a corresponding qualifier for the DefaultDS and add it to the DatabaseProducer

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface DefaultDatabase {
}

 

public class DatabaseProducer {

    @Produces
    @PersistenceContext(unitName = "primary")
    @MySQLDatabase
    private EntityManager em;

    @Produces
    @PersistenceContext(unitName = "secondary")
    @DefaultDatabase
    private EntityManager em;
}


This way you can immediatly give evidence of what you are doing with your Entity Managers.