In this recipe, we will learn how to create and populate the Patient and a Medication table. These tables will be used for the other recipes in this chapter. This approach means you do not have to import or otherwise use an existing database. The process of creating these tables is facilitated through several helper methods. Upon completion of this recipe, you will have the base for learning how to use JPQL as illustrated in the remaining recipes.
The process of creating this application consists of:
We will start with the description of a patient and a medication entity. The facade classes are then defined and a servlet will be created to actually use the facade classes to populate the tables.
The Patient
class represents a patient with several attributes:
id
A long integer automatically generatedfirstName
A simple stringlastName
A simple stringsex
A characterdateOfBirth
An instance of the java.util.Date
classmedications
A collection of medication for the patientThe Medication
class represents a medication with several attributes:
name
The name of the drugtype
The type of the drugdosage
The dosage levelfrequency
The frequency the medication is takenpatient
A reference to the patient using this medicationCreate a new Java EE application called PatientApplication
. Add a package called packt
to the EJB module and a package called servlet
to the WAR module.
We will create two entity classes that deal with patients and their medications; Patient
and Medication
. A patient can have zero or more medications. This relationship between the entities is called a One-To-Many relationship.
Create the Patient
entity in the package packt
. The creation of an entity is detailed in the Chapter 4, Creating an entity recipe. We will augment this entity with the @Table annotation to associate the entity with the table PATIENT. Add fields for the patient attributes listed previously along with getter and setter methods. The fields are annotated with @Column which specifies the field name for the corresponding table. In addition, we will need constructors and two methods: addMedication
and removeMedication
which associates a medication with a patient. Until the Medication
class is added, these methods will result in a syntax error.
@Entity @Table(name="PATIENT") public class Patient implements Serializable { @Column(name="FIRSTNAME") private String firstName; @Column(name="LASTNAME") private String lastName; @Column(name="SEX") private char sex; @Column(name="DATEOFBIRTH") @Temporal(javax.persistence.TemporalType.DATE) private Date dateOfBirth; @OneToMany(mappedBy="patient") private Collection<Medication> medications; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; public Patient() { } public Patient(String firstName, String lastName, char sex, Date dob) { this.firstName = firstName; this.lastName = lastName; this.sex = sex; this.dateOfBirth = dob; } public void addMedication(Medication medication) { medications.add(medication); } public Medication removeMedication(Medication medication) { medications.remove(medication); medication.setPatient(null); return medication; }
Next, add the Medication
entity to the packt
package. Use the @Table annotation to associate this entity with the MEDICATION table. Add getter and setter methods to the class for the fields listed earlier. Also add a default and four argument constructor to facilitate the construction of a Medication
instance.
@Entity @Table(name = "MEDICATION") public class Medication implements Serializable { @ManyToOne private Patient patient; @Column(name = "NAME") private String name; @Column(name = "TYPE") private String type; @Column(name = "DOSAGE") private int dosage; @Column(name = "FREQUENCY") private int frequency; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; public Medication() { } public Medication(String medication, String type, int dosage, int frequency) { this.patientId = patientId; this.name = medication; this.type = type; this.dosage = dosage; this.frequency = frequency; } public Patient getPatient() { return patient; } public void setPatient(Patient patient) { this.patient = patient; }
Create and add an AbstractFacade
class to the packt
package as detailed in the previous chapter. Also add a PatientFacade
and a MedicationFacade
class to persist the entities as discussed in Chapter 4, Creating an entity facade recipe. We will later add methods to these classes to illustrate the use of JPQL and the Criteria API.
The last class we need to create is the PatientServlet
which we will add to the servlet
package. Here, only the first part of the servlet is shown. The basic servlet class is discussed in Chapter 1, Accessing a session bean using dependency injection recipe. Note the declaration and injection of the entity class and their facade class variables. These will be used later to illustrate the use of JPQL.
public class PatientServlet extends HttpServlet { private Patient patient; @EJB private PatientFacade patientFacade; private Medication medication; @EJB private MedicationFacade medicationFacade; // Helper methods protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { // Populate the tables populateTables(); ... } finally { out.close(); } } ... }
Our main task here is to populate the PATIENT and MEDICATION tables. To assist in this process create two methods: createPatient
and createMedication
, and add them after the helper methods comment. Also, add a method called populateTables
to actually add entries to these tables.
// Helper methods private Patient createPatient(String firstName, String lastName, char sex, int year, int month, int day) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month, day); patient = new Patient(firstName, lastName, sex, calendar.getTime()); patientFacade.create(patient); return patient; } private Medication createMedication(String name, String type, int dosage, int frequency) { Medication medication; medication = new Medication(name, type, dosage, frequency); medicationFacade.create(medication); return medication; } private void populateTables() { patient = createPatient("Donald", "Baker", 'M', 1976, 3, 13); patient.addMedication(createMedication("Accupril", "ACE", 10, 1)); patient.addMedication(createMedication("Cleocin", "Anti-Bacterial", 2, 2)); patient = createPatient("Jennifer", "Campbell", 'F', 1982, 5, 23); patient.addMedication(createMedication("Urex", "Anti-Bacterial", 5, 2)); patient.addMedication(createMedication("Lasix", "Diuretic", 12, 1)); patient = createPatient("Steven", "Young", 'M', 1965, 6, 12); patient.addMedication(createMedication("Vasitec", "ACE", 10, 2)); patient = createPatient("George", "Thompson", 'M', 1957, 12, 2); patient.addMedication(createMedication("Altace", "ACE", 25, 1)); patient.addMedication(createMedication("Amoxil", "Anti-Bacterial", 10, 4)); patient.addMedication(createMedication("Mycelex", "Anti-Fungal", 12, 2)); patient = createPatient("Sandra", "Taylor", 'F', 1998, 1, 23); patient.addMedication(createMedication("Accupril", "ACE", 10, 1)); patient = createPatient("Maria", "Green", 'F', 1978, 7, 21); patient.addMedication(createMedication("Altace", "ACE", 25, 1)); patient = createPatient("Sarah", "Walker", 'F', 1980, 10, 10); patient.addMedication(createMedication("Accupril", "ACE", 10, 1)); patient.addMedication(createMedication("Ilosone", "Anti-Bacterial", 5, 2)); patient.addMedication(createMedication("Terazol", "Anti-Fungal", 20, 1)); patient.addMedication(createMedication("Aldactone", "Diuretic", 5, 3)); patient = createPatient("Kevin", "Hall", 'M', 2005, 4, 2); patient = createPatient("Carol", "Harris", 'F', 1958, 8, 11); patient.addMedication(createMedication("Zyvox", "Anti-Bacterial", 10, 3)); }
When the servlet is executed the tables should be created and populated.
In this recipe we set up the foundation for the other recipes in this chapter. While we now have populated these tables, it would be nice if we could examine and verify that our code works as expected. We will delay this activity until the Using the Select query recipe.
Let's examine the Patient
class first. Notice the use of the @OneToMany annotation. One patient entity may possess zero or more medications. The mappedBy
attribute indicates a bi-directional relationship. This means we can use JPQL or the Criteria API to navigate in either direction.
Getter and setter methods are easy to add to a class. Most IDEs provide some mechanism to quickly generate and insert these methods based on the existing class fields. For example, from NetBeans right-clicking on the source code and selecting the insert code menu allows you to use a Getter option that presents a set of options for generating these types of methods.
The dateOfBirth
field was declared as a Date
. Either the java.util.Date
or the java.sql.Date
class could have been used. The java.util.Date
stores a date as a long value representing the time elapsed since January 1, 1970 00:00:00.000 Greenwich Mean Time. The java.sql.Date
class extends the java.util.Date
class and is used where a JDBC SQL DATE value is used. The use of time is covered in more detail in Chapter 12, Using time within an EJB recipe.
In the Medication
entity notice the use of the @ManyToOne annotation. It was used to create a bi-directional connection between the Patient
and Medication
entities. It allowed us to determine which patient uses which medication.
In the servlet, the createPatient
and createMedication
methods used their arguments as parameters to their respective constructors. The createPatient
method also used a Calendar
instance to convert the date information into a form assignable to the Patient's dateOfBirth
field.
The populateTables
method used these helper methods to populate the database. This simple, but lengthy method added a series of patients each with zero or more medications.
Throughout this chapter we will create and use queries to illustrate the various techniques available. Some of these queries will retrieve information from a table while others may delete and modify the contents of a table. In order to insure consistent and predictable behavior, it is best if the tables always start with the same initial contents. We can insure this by removing and then restoring the contents of the tables each time the PatientServlet
executes. By using the following code we can make this possible. The findAll
method is part of the facade classes and returns a list of all of the entities in that table. Add the following code sequence before the call to the populateTables
method.
// Remove all medications from the database List<Patient> patientList = patientFacade.findAll(); for (Patient patient : patientList) { patientFacade.remove(patient); } // Remove all medications from the database List<Medication> medicationList = medicationFacade.findAll(); for (Medication medication : medicationList) { medicationFacade.remove(medication); } // Populate the tables populateTables();
3.137.174.23