금요일, 3월 29
Shadow

#033 Java EE 6 – JPA 2.0

Lab Exercises

For the sake of the simplicity of the lab, most exercises are provided in the form of “ready-to-open-and-run” NetBeans projects.  (Many of them are borrowed from “glassfish-samples” and “Java EE 6 tutorial“.)  Please feel free to create them from scratch if you want to.

It is strongly encouraged, leveraging what is provided in this lab, you do your own experimentation meaning creating/adding your own code as much as you can.

If you have written some code that might help everyone else, please feel free to share them on this codecamp email alias or directly send them to the instructors.  Your name will be recognized in this lab if your sample code is chosen to be included.  For the tasks that need to be done, please see the “Things to be done” section above.)

 

 Before you start this lab, you have to get sample applications from “glassfish-samples” and “Java EE tutorial” as described in LAB-4530: Java EE 6 – Examples.

 

Exercise 0: Build standalone JPA application step by step

In this exercise, you are going to build a simple standalone (Java SE) JPA application step by step.  Since many of the sample applications you are going to build and run in this lab are “ready to open and run” standalone applications, it would be useful for you to know how those applications were built.

(0.1) Start Java DB database server

0. Start NetBeans IDE.
1. Start Java DB database server.

  • Select Services tab.
  • Expand Databases.
  • Right click Java DB and select Start Server.


Figure-0.11

(0.2) Build a simple “helloworld” standalone JPA application

1. Create a new Java Application project.

  • Select File from top-level menu and select New Project.


Figure-0.21

  • Select Java under Categories on the left and Java Application under Projects on the right.
  • Click Next.


Figure-0.22

  • For the Project Name field, enter jpa2.0_helloworld (or whatever project name of your choice).
  • Click Finish.


Figure-0.23

2. Create Person Entity class.

  • Right click jpa20_helloworld package and select New->Java Class. (Or you can select Entity Class if it is in the pop-up menu.)


Figure-0.24

  • For the Class Name field, enter Person.
  • Click Finish.


Figure-0.25

  • Modify IDE generated Person.java with the one below.  Note that Person class is POJO class annotated with @Entity.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package jpa20_helloworld;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
*
* @author sang
*/
@Entity
public class Person {
@Id
@GeneratedValue
private int id;
private String name;
private long salary;

/**
* @return the id
*/
public int getId() {
return id;
}

/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}

/**
* @return the name
*/
public String getName() {
return name;
}

/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}

/**
* @return the salary
*/
public long getSalary() {
return salary;
}

/**
* @param salary the salary to set
*/
public void setSalary(long salary) {
this.salary = salary;
}

}

  • Observe that there are compile errors.  This is expected because the libraries are not added yet to the project.


Figure-0.26

3. Add libraries.

  • Right click Libraries of the project and select Add Library.


Figure-0.27

  • Observe that Add Library dialog box appears.
  • Select EclipseLink(JPA2.0), EclipseLink-GlassFish-v3, Java DB Driver, Java-EE-GlassFish-v3 and click Add Library button.


Figure-0.28

  • Observe that the compile errors are gone.

 Trouble-shooting: If you don’t see Java DB Driver somehow, please add derbyclient.jar instead. (The Java DB Driver library is made of derbyclient.jar file.)  The derbyclient.jar is available under GLASSFISH_HOME/javadb/lib directory.  For your convenience, it is also provided under <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/clientdrivers directory.  The step to take is right clicking Libraries and select Add JAR/Folder.

4. Create persistence unit (persistence.xml).

  • Click Save all files… button so that the Person class be known to the persistence unit you are going to create.
  • Right click project and select New->Other.


Figure-0.29

  • Select Persistence under Categories on the left and select Persistence Unit under File Types on the right.
  • Click Next.


Figure-0.30

  • For Database Collection field, select jdbc:derby://localhost:1527/sample [app on APP].  This is to select sample database as an actual database for persistence operation.  (The sample database is a built-in database that comes with GlassFish.)
  • For Table Generation Strategy, select Drop and Create.  When chosen, this strategy lets you drop existing tables and create new ones.  Given that you are going to run this application multiple times, this is the most convenient table generation strategy.
  • Click Finish.


Figure-0.31

5. Add Entity class to persistence unit.

  • Click Add Class button on the section of Include Entity Classes section at the bottom.


Figure-0.32

  • Select jpa20_helloworld.Person and click OK.


Figure-0.33

6. Modify Main.java as shown below.  It creates two Person instances and persists them into the PERSON table in the sample database.

package jpa20_helloworld;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

/**
*
* @author sang
*/
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// Create EntityManager
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“jpa2.0_helloworldPU”);
EntityManager em = emf.createEntityManager();

EntityTransaction tx = em.getTransaction();
tx.begin();

Person p1 = new Person();
p1.setName(“Sang Shin”);
p1.setSalary(10000);
em.persist(p1);

Person p2 = new Person();
p2.setName(“Annie Song”);
p2.setSalary(50000);
em.persist(p2);

tx.commit();

em.close();
emf.close();
}

}

Main.java

6. Build and run the application.

  • Right click project and select Run.


Figure-0.34

  • Make sure the build has been successful.


Figure-0.35

 Trouble-shooting: If you experience “..Person… is not a known entity type” error condition as shown below, it is because you have not added the Person class as entity class to the persistence.xml as described above.


Figure-0.36

 Trouble-shooting:  You will see the following [EL Warning] condition overtime you run the application – and the rest of the sample applications in this hands-on lab.  This is expected and benign warning message.  The reason you get this warning is because the ID generation strategy of the Person entity class is set with @GeneratedValue.  What this means is you are asking the persistence provider to generate an ID for each newly created entry in the PERSON table.  And the persistence provider is internally using SEQUENCE table for computing the next ID value.  Now the persistence provider will try to create a new SEQUENCE table whenever the application is run but found that it already exists and displays a warning.  If you delete SEQUENCE table manually, you will not see this warning, by the way, just as an experimentation.

[EL Warning]: 2010-01-14 10:57:09.204–ServerSession(27653945)–Exception [EclipseLink-4002] (Eclipse Persistence Services – 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Table/View ‘SEQUENCE’ already exists in Schema ‘APP’.
Error Code: -1
Call: CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))


Figure-0.37

7. Verify the PERSON table has been created.

  • Click Services tab.
  • Expand Databases.
  • Right click jdbc:derby://localhost:1527/sample [app on APP] and select Connect.


Figure-0.38

  • Expand App->Tables.
  • Right click PERSON and select View Data.


Figure-0.39

  • Verify that the PERSON table now has two entries.


Figure-0.40

8. Add JPAUtil class under jpa20_helloworld.util package.  JPAUtil class is a collection of utility classes including checkData() method that displays the entries of a table.

package jpa20_helloworld.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;

public class JPAUtil {

// Database configuration
public static String url = “jdbc:derby://localhost:1527/sample”;
public static String dbdriver = “org.apache.derby.jdbc.ClientDriver”;
public static String username = “app”;
public static String password = “app”;
static Statement st;
static Connection conn;

static {
try {
Class.forName(dbdriver);
conn = DriverManager.getConnection(url, username, password);
st = conn.createStatement();
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println(“Initial SessionFactory creation failed.” + ex);
throw new ExceptionInInitializerError(ex);
}
}

public static void setup(String sql) {
try {
createStatement();
st.executeUpdate(sql);
} catch (Exception e) {
System.err.println(“Got an exception! “);
e.printStackTrace();
System.exit(0);
}
}

public static void createStatement() {
try {
Class.forName(dbdriver);
conn = DriverManager.getConnection(url, username, password);
st = conn.createStatement();
} catch (Exception e) {
System.err.println(“Got an exception! “);
e.printStackTrace();
System.exit(0);
}
}

// Drop table if exists
public static void droptable(String sql) {
try {
createStatement();
st.executeUpdate(sql);
} catch (Exception e) {
}
}

public void executeSQLCommand(String sql) throws Exception {
st.executeUpdate(sql);
}

public static void checkData(String sql) {
String[] starray = sql.split(” “);
System.out.println(“\n******** Table: ” + starray[starray.length – 1] + ” *******”);
try {
createStatement();
ResultSet rs = st.executeQuery(sql);
outputResultSet(rs);
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void outputResultSet(ResultSet rs) throws Exception {
ResultSetMetaData metadata = rs.getMetaData();

int numcols = metadata.getColumnCount();
String[] labels = new String[numcols];
int[] colwidths = new int[numcols];
int[] colpos = new int[numcols];
int linewidth;

linewidth = 1;
for (int i = 0; i < numcols; i++) {
colpos[i] = linewidth;
labels[i] = metadata.getColumnLabel(i + 1); // get its label
int size = metadata.getColumnDisplaySize(i + 1);
if (size > 30 || size == -1) {
size = 30;
}
int labelsize = labels[i].length();
if (labelsize > size) {
size = labelsize;
}
colwidths[i] = size + 1; // save the column the size
linewidth += colwidths[i] + 2; // increment total size
}

StringBuffer divider = new StringBuffer(linewidth);
StringBuffer blankline = new StringBuffer(linewidth);
for (int i = 0; i < linewidth; i++) {
divider.insert(i, ‘-‘);
blankline.insert(i, ” “);
}
// Put special marks in the divider line at the column positions
for (int i = 0; i < numcols; i++) {
divider.setCharAt(colpos[i] – 1, ‘+’);
}
divider.setCharAt(linewidth – 1, ‘+’);

// Begin the table output with a divider line
System.out.println(divider);

// The next line of the table contains the column labels.
// Begin with a blank line, and put the column names and column
// divider characters “|” into it. overwrite() is defined below.
StringBuffer line = new StringBuffer(blankline.toString());
line.setCharAt(0, ‘|’);
for (int i = 0; i < numcols; i++) {
int pos = colpos[i] + 1 + (colwidths[i] – labels[i].length()) / 2;
overwrite(line, pos, labels[i]);
overwrite(line, colpos[i] + colwidths[i], ” |”);
}
System.out.println(line);
System.out.println(divider);

while (rs.next()) {
line = new StringBuffer(blankline.toString());
line.setCharAt(0, ‘|’);
for (int i = 0; i < numcols; i++) {
Object value = rs.getObject(i + 1);
if (value != null) {
overwrite(line, colpos[i] + 1, value.toString().trim());
overwrite(line, colpos[i] + colwidths[i], ” |”);
}
}
System.out.println(line);
}
System.out.println(divider);

}

static void overwrite(StringBuffer b, int pos, String s) {
int len = s.length();
for (int i = 0; i < len; i++) {
b.setCharAt(pos + i, s.charAt(i));
}
}
}

JPAUtil.java


Figure-0.41

9. Modify Main.java to use checkData() method to display the entries of the table.

package jpa20_helloworld;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import jpa20_helloworld.util.JPAUtil;

/**
*
* @author sang
*/
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// Create EntityManager
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“jpa2.0_helloworldPU”);
EntityManager em = emf.createEntityManager();

EntityTransaction tx = em.getTransaction();
tx.begin();

Person p1 = new Person();
p1.setName(“Sang Shin”);
p1.setSalary(10000);
em.persist(p1);

Person p2 = new Person();
p2.setName(“Annie Song”);
p2.setSalary(50000);
em.persist(p2);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from PERSON”);

em.close();
emf.close();
}
}

Main.java

10. Run the application again.

  • Observe that the entries of the PERSON table gets displayed in the Output window.


Figure-0.42

11. Display context sensitive Javadoc on any JPA classes.  Please use context sensitive Javadoc for any JPA classes you want to learn about moving forward.

  • Right click the @Entity in the editor window and select Show Javadoc.


Figure-0.43

  • Observe that Javadoc of the @Entity class appears in the browser.


Figure-0.44

Solution: The solution of this exercise is available as jpa2.0_helloworld project under <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/solutions.  You can just open it and run it.

Summary

In this exercise,  you have built a simple standalone Java SE application which uses persistence step by step.

Exercise 1: Mapping with @ElementCollection

In JPA 2.0, rich mapping capabilities are added.  For example, an entity can have a collection of basic types or Embeddable’s.  (In JPA 1.0, an entity can have a collection of only entity type.)  An Embeddable can have another Embeddable and Embeddable can have a one-to-many relationship with entity type.  In this exercise, you are going to exercise these new mapping features.

(1.1) Collection of basic type

In this example, you are going to see how an Employee entity can have a collection of a Skill, which is String type, through the usage of @ElementCollection annotation.  You are going to build and run the application and then explore the code next.

1. Open jpa2.0_mapping_collection_basictypes NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
    • Windows: If you unzipped the 4537_javaee6_jpa2.0.zip file under C:\handsonlabs directory, the directory to which you want to browse down should be C:\handsonlabs\javaee6_jpa2.0\samples.
    • Solaris/Linux/Mac: If you unzipped the 4537_javaee6_jpa2.0.zip file under $HOME/handsonlabs directory, the directory to which you want to browse down should be $HOME/handsonlabs/javaee6_jpa2.0/samples.
  • Select jpa2.0_mapping_collection_basictypes.
  • Click Open Project.
  • Observe that the jpa2.0_mapping_collection_basictypes project node appears under Projects tab window.

2. Build and run jpa2.0_mapping_collection_basictypes project.

  • Right-click jpa2.0_mapping_collection_basictypes project and select Run.
  • Observe the result in the Output window.

Figure-1.11
 Trouble-shooting: If you experience the following error condition, it is because you have not started Java DB database server. Start the Java DB server as shown above.


Figure-1.12

(1.2) Study code

1. Employee.java.

  • Observe that the Employee entity has a set of String basic type through the usage of @ElementCollection annotation.


Figure-1.21

package examples.model;

import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Employee {

@Id
@GeneratedValue
@Column(name = “EMPLOYEE_ID”)
private int id;
private String name;
private long salary;

// Collection of basic type – String type in this case
@ElementCollection
// Name the table as “expertise”
@CollectionTable(name = “expertise”)
private Set<String> javaskills;

public Employee() {
}

public Employee(int id) {
this.id = id;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

@Override;
public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}

/**
* @return the javaskills
*/
public Set<String> geJavaskills() {
return javaskills;
}

/**
* @param javaskills the javaskills to set
*/
public void seJavaskills(Set<String> javaskills) {
this.javaskills = javaskills;
}
}

Employee.java

2. persistence.xml.

  • Note that the properties are now standardized in JPA 2.0.  For example, instead of toplink.jdbc.driver for the Toplink or another name for another persistence provider, you are going to use standardized javax.persistence.jdbc.driver.
  • Note that we are using drop-and-create-tables  (Drop and  Create tables)  strategy, which means the  persistence provider will drop  existing EMPLOYEE and EXPERTISE tables and recreate them everytime you  run the application.


Figure-1.22

<?xml version=”1.0″ encoding=”UTF-8″?>
<persistence version=”1.0″ xmlns=”http://java.sun.com/xml/ns/persistence”>
<persistence-unit name=”EmployeeService” transaction-type=”RESOURCE_LOCAL”>
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>examples.model.Employee</class>
<properties>
<property name=”eclipselink.target-database” value=”DERBY”/>
<!–<property name=”eclipselink.ddl-generation” value=”create-tables”/>–>
<property name=”eclipselink.ddl-generation” value=”drop-and-create-tables”/>
<property name=”eclipselink.logging.level” value=”INFO”/>
<property name=”javax.persistence.jdbc.driver” value=”org.apache.derby.jdbc.ClientDriver”/>
<property name=”javax.persistence.jdbc.url” value=”jdbc:derby://localhost:1527/sample”/>
<property name=”javax.persistence.jdbc.user” value=”app”/>
<property name=”javax.persistence.jdbc.password” value=”app”/>
<property name=”” value=”app”/>
</properties>
</persistence-unit>
</persistence>

persistence.xml

3. Main.java.

  • The Main class provides a testing code, in which a couple of Employee entities with a collection of String type are created. The contents of the database tables are then displayed so that you can tell if the tables are created and correct data are persisted.
package mypackage;

import examples.model.Employee;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.EmployeeService;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.EntityTransaction;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

// Create EntityManager
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

// EmployeeService is a utility class
EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

Employee emp = es.createEmployee(“Sang Shin”, 10000);
Set<String> javaskills = new HashSet<String>();
javaskills.add(“servlet 3.0”);
javaskills.add(“ejb 3.1”);
javaskills.add(“jsf 2.0”);
javaskills.add(“jpa 2.0”);
es.setJavaskills(emp, javaskills);

emp = es.createEmployee(“Bill Clinton”, 8000);
javaskills = new HashSet<String>();
javaskills.add(“jsf”);
javaskills.add(“ejb”);
es.setJavaskills(emp, javaskills);

es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
es.createEmployee(“Charles Lannie”, 7500);
es.createEmployee(“Shelley Nichole”, 8500);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);
JPAUtil.checkData(“select * from EXPERTISE”);

em.close();
emf.close();

}
}

Main.java

4.  EmployeeService.java.  The EmployeeService class is utility class which provide a few convenience methods.

package examples.model;

import java.util.Collection;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.Query;

public class EmployeeService {

protected EntityManager em;

public EmployeeService(EntityManager em) {
this.em = em;
}

public Employee createEmployee(String name, long salary) {
Employee emp = new Employee();
emp.setName(name);
emp.setSalary(salary);
em.persist(emp);
return emp;
}

public Employee updateEmployee(Employee emp) {
em.persist(emp);
return emp;
}

public void setJavaskills(Employee emp, Set<String> javaskills) {
if (emp != null) {
emp.seJavaskills(javaskills);
}
}

public void removeEmployee(int id) {
Employee emp = findEmployee(id);
if (emp != null) {
em.remove(emp);
}
}

public Employee raiseEmployeeSalary(int id, long raise) {
Employee emp = em.find(Employee.class, id);
if (emp != null) {
emp.setSalary(emp.getSalary() + raise);
}
return emp;
}

public Employee findEmployee(int id) {
return em.find(Employee.class, id);
}

public Collection<Employee> findAllEmployees() {
Query query = em.createQuery(“SELECT e FROM Employee e”);
return (Collection<Employee>) query.getResultList();
}
}

EmployService.java

(1.3) Collection of Embeddable

In JPA 2.0, an entity class can also have a collection of Embeddable’s.  In this example, an Employee entity has a collection of Address class, which is Embeddable type.

1. Open jpa2.0_mapping_collection_embeddables NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_mapping_collection_embeddables.
  • Click Open Project.
  • Observe that the jpa2.0_mapping_collection_embeddables project node appears under Projects tab window.

2. Build and run jpa2.0_mapping_collection_embeddables project.

  • Right-click jpa2.0_mapping_collection_embeddables project and select Run.
  • Observe the result in the Output window.

Figure-1.31

(1.4) Study code

1. Employee.java.  Note that Employee entity class has a set of Address, which is an Embeddable type.

package examples.model;

import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Employee {

@Id
@GeneratedValue
@Column(name = “EMPLOYEE_ID”)
private int id;
private String name;
private long salary;

// Collection of basic type – String type in this case
@ElementCollection
// Name the table as “expertise”
@CollectionTable(name = “expertise”)
private Set<String> javaskills;

// Collection of embeddable type
@ElementCollection
// Name the table as “expertise”
@CollectionTable(name = “vacationhomes”)
private Set<Address> vacationHomes;

public Employee() {
}

public Employee(int id) {
this.id = id;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

@Override;
public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}

/**
* @return the javaskills
*/
public Set<String> geJavaskills() {
return javaskills;
}

/**
* @param javaskills the javaskills to set
*/
public void seJavaskills(Set<String> javaskills) {
this.javaskills = javaskills;
}

/**
* @return the vacationHomes
*/
public Set<Address> getVacationHomes() {
return vacationHomes;
}

/**
* @param vacationHomes the vacationHomes to set
*/
public void setVacationHomes(Set<Address> vacationHomes) {
this.vacationHomes = vacationHomes;
}
}

Employee.java

2. Address.java.  Note that Address class is an Embeddable type.

package examples.model;

import java.io.Serializable;
import javax.persistence.Embeddable;

@Embeddable
public class Address implements Serializable{
private String street;
private String city;
private String state;

public Address(){

}

public Address(String street, String city, String state) {
this.street = street;
this.city = city;
this.state = state;
}

/**
* @return the street
*/
public String getStreet() {
return street;
}

/**
* @param street the street to set
*/
public void setStreet(String street) {
this.street = street;
}

/**
* @return the city
*/
public String getCity() {
return city;
}

/**
* @param city the city to set
*/
public void setCity(String city) {
this.city = city;
}

/**
* @return the state
*/
public String getState() {
return state;
}

/**
* @param state the state to set
*/
public void setState(String state) {
this.state = state;
}
}

Address.java

3. Main.java

package mypackage;

import examples.model.Address;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.EmployeeService;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.EntityTransaction;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

es.createEmployee(“Sang Shin”, 10000);
Set<String> javaskills = new HashSet<String>();
javaskills.add(“servlet”);
javaskills.add(“ejb”);
es.setJavaskills(1, javaskills);

Set<Address> vacationHomes = new HashSet<Address>();
vacationHomes.add(new Address(“1 dreamland st”, “newton”, “MA”));
vacationHomes.add(new Address(“22 marthas vineyard”, “cape cod”, “MA”));
es.setVacationHomes(1, vacationHomes);

es.createEmployee(“Bill Clinton”, 8000);
javaskills = new HashSet<String>();
javaskills.add(“jsf”);
javaskills.add(“ejb”);
es.setJavaskills(2, javaskills);

es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
es.createEmployee(“Charles Lannie”, 7500);
es.createEmployee(“Shelley Nichole”, 8500);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);
JPAUtil.checkData(“select * from EXPERTISE”);
JPAUtil.checkData(“select * from VACATIONHOMES”);

em.close();
emf.close();

}
}

Main.java

 

(1.5) Multi-level Embeddables

In JPA 2.0, an Embeddable class can have child Embedable class, thus constructing multi-level Embeddable sructure.  In this example, ContactInfo Embeddable has Address Embeddable as an attribute.

1. Open jpa2.0_mapping_collection_embeddables_multilevels NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_mapping_collection_embeddables_multilevels.
  • Click Open Project.
  • Observe that the jpa2.0_mapping_collection_embeddables_multilevels project node appears under Projects tab window.

2. Build and run jpa2.0_mapping_collection_embeddables_multilevels project.

  • Right-click jpa2.0_mapping_collection_embeddables_multilevels project and select Run.
  • Observe the result in the Output window.

Figure-1.51

(1.6) Study code

1.  Employee.java.  Note that Employee entity class has ContactInfo class, which is Embeddable type. The ContactInfo Embeddable class has Address Embeddable as a child.

package examples.model;

import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Employee {

@Id
@GeneratedValue
@Column(name = “EMPLOYEE_ID”)
private int id;
private String name;
private long salary;

// Collection of basic type – Stting type in this case
@ElementCollection
// Name the table as “expertise”
@CollectionTable(name = “expertise”)
private Set<String> javaskills;

// Collection of embeddable type
@ElementCollection
@CollectionTable(name = “vacationhomes”)
private Set<Address> vacationHomes;

// Multi-levels of Embeddable
private ContactInfo contactInfo;

public Employee() {
}

public Employee(int id) {
this.id = id;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

@Override;
public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}

/**
* @return the javaskills
*/
public Set<String> geJavaskills() {
return javaskills;
}

/**
* @param javaskills the javaskills to set
*/
public void seJavaskills(Set<String> javaskills) {
this.javaskills = javaskills;
}

/**
* @return the vacationHomes
*/
public Set<Address> getVacationHomes() {
return vacationHomes;
}

/**
* @param vacationHomes the vacationHomes to set
*/
public void setVacationHomes(Set<Address> vacationHomes) {
this.vacationHomes = vacationHomes;
}

/**
* @return the contactInfo
*/
public ContactInfo getContactInfo() {
return contactInfo;
}

/**
* @param contactInfo the contactInfo to set
*/
public void setContactInfo(ContactInfo contactInfo) {
this.contactInfo = contactInfo;
}
}

Employee.java

2. ContactInfo.java.

package examples.model;

import java.io.Serializable;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;

@Embeddable
public class ContactInfo implements Serializable{
@Embedded private Address address;

public ContactInfo(){
}

public ContactInfo(Address address) {
this.address = address;
}

/**
* @return the address
*/
public Address getAddress() {
return address;
}

/**
* @param address the address to set
*/
public void setAddress(Address address) {
this.address = address;
}

}

ContactInfo.java

3. Address.java

package examples.model;

import java.io.Serializable;
import javax.persistence.Embeddable;

@Embeddable
public class Address implements Serializable{
private String street;
private String city;
private String state;

public Address(){

}

public Address(String street, String city, String state) {
this.street = street;
this.city = city;
this.state = state;
}

/**
* @return the street
*/
public String getStreet() {
return street;
}

/**
* @param street the street to set
*/
public void setStreet(String street) {
this.street = street;
}

/**
* @return the city
*/
public String getCity() {
return city;
}

/**
* @param city the city to set
*/
public void setCity(String city) {
this.city = city;
}

/**
* @return the state
*/
public String getState() {
return state;
}

/**
* @param state the state to set
*/
public void setState(String state) {
this.state = state;
}
}

Address.java

4. Main.java.

package mypackage;

import examples.model.Address;
import examples.model.ContactInfo;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.EmployeeService;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.EntityTransaction;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

// First employee
es.createEmployee(“Sang Shin”, 10000);

Set<String> javaskills = new HashSet<String>();
javaskills.add(“servlet”);
javaskills.add(“ejb”);
es.setJavaskills(1, javaskills);

Set<Address> vacationHomes = new HashSet<Address>();
vacationHomes.add(new Address(“1 dreamland st”, “newton”, “MA”));
vacationHomes.add(new Address(“22 marthas vineyard”, “cape cod”, “MA”));
es.setVacationHomes(1, vacationHomes);

ContactInfo contactInfo = new ContactInfo(new Address(“1 dreamland road”, “Newton”, “MA”));
es.setContactInfo(1, contactInfo);

// 2nd employee
es.createEmployee(“Bill Clinton”, 8000);
javaskills = new HashSet<String>();
javaskills.add(“jsf”);
javaskills.add(“ejb”);
es.setJavaskills(2, javaskills);

es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
es.createEmployee(“Charles Lannie”, 7500);
es.createEmployee(“Shelley Nichole”, 8500);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);
JPAUtil.checkData(“select * from EXPERTISE”);
JPAUtil.checkData(“select * from VACATIONHOMES”);

em.close();
emf.close();

}
}

Main.java

 

(1.7) Embeddable with its own relationship

An Embeddable can have one-to-many or many-to-many relationship with other entities.  In this example, ContactInfo Embeddable class has one-to-many relationship with Phone entities.

1. Open jpa2.0_mapping_collection_embeddables_relation NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_mapping_collection_embeddables_relation.
  • Click Open Project.
  • Observe that the jpa2.0_mapping_collection_embeddables_relation project node appears under Projects tab window.

2. Build and run jpa2.0_mapping_collection_embeddables_relation project.

  • Right-click jpa2.0_mapping_collection_embeddables_relation project and select Run.
  • Observe the result in the Output window.

Figure-1.71

(1.8) Study code

1. Employee.java

package examples.model;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Employee implements Serializable {

@Id
@GeneratedValue
@Column(name = “EMPLOYEE_ID”)
private int id;
private String name;
private long salary;

// Multi-levels of Embeddable
private ContactInfo contactInfo;

public Employee() {
}

public Employee(int id) {
this.id = id;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

@Override;
public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}

/**
* @return the contactInfo
*/
public ContactInfo getContactInfo() {
return contactInfo;
}

/**
* @param contactInfo the contactInfo to set
*/
public void setContactInfo(ContactInfo contactInfo) {
this.contactInfo = contactInfo;
}
}

Employee.java

2. ContactInfo.java.  Note that the ContactInfo class, which is@Embeddable type, has one-to-many bidirectional relationship with Phone entity class.

package examples.model;

import java.io.Serializable;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.OneToMany;

@Embeddable
public class ContactInfo implements Serializable{
@Embedded private Address address;

// One-to-many bidirectional relationship between
// ContactInfo and Phone.
// The “employee” is a field in the Phone.
@OneToMany(cascade=CascadeType.ALL, mappedBy=”employee”)
private Set<Phone> phones;

public ContactInfo(){
}

public ContactInfo(Address address) {
this.address = address;
}

/**
* @return the address
*/
public Address getAddress() {
return address;
}

/**
* @param address the address to set
*/
public void setAddress(Address address) {
this.address = address;
}

/**
* @return the phones
*/
public Set<Phone> getPhones() {
return phones;
}

/**
* @param phones the phones to set
*/
public void setPhones(Set<Phone> phones) {
this.phones = phones;
}

}

ContactInfo.java

3. Phone.java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = “PHONE_TABLE”)
public class Phone implements Serializable {

@Id
@Column(name = “PHONE_ID”)
@GeneratedValue
private int id;
private String phoneNumber;

// Bi-directional one-to-many relationship
@ManyToOne(optional = true)
private Employee employee;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public Phone() {
}

public Phone(String phoneNumber, Employee emp) {
this.phoneNumber = phoneNumber;
this.employee = emp;
}

public Phone(int id, String phoneNumber) {
this.id = id;
this.phoneNumber = phoneNumber;
}

public String getPhoneNumber() {
return phoneNumber;
}

/**
* @param phoneNumber the phoneNumber to set
*/
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}

/**
* @return the employee
*/
public Employee getEmployee() {
return employee;
}

/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
}

Phone.java

4. Main.java

package mypackage;

import examples.model.Address;
import examples.model.ContactInfo;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import examples.model.Phone;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

// First employee
Employee emp = es.createEmployee(“Sang Shin”, 10000);
Set<Phone> phones = new HashSet<Phone>();
phones.add(new Phone(“111-3333-3333”, emp));
phones.add(new Phone(“111-1233-6666”, emp));
ContactInfo contactInfo = new ContactInfo(new Address(“1 dreamland road”, “Newton”, “MA”));
contactInfo.setPhones(phones);
es.setContactInfo(emp, contactInfo);
es.updateEmployee(emp);

// Second employee
emp =  es.createEmployee(“Bill Clinton”, 8000);
phones = new HashSet<Phone>();
phones.add(new Phone(“222-3333-3333”, emp));
phones.add(new Phone(“222-1233-6666”, emp));
contactInfo = new ContactInfo(new Address(“7 Green St”, “Ohmygodgown”, “PA”));
contactInfo.setPhones(phones);
es.setContactInfo(emp, contactInfo);
es.updateEmployee(emp);

// Perform query – Retrieve all employees whose street is
// “1 dteamland road”.
String jpql = “SELECT e FROM Employee e WHERE e.contactInfo.address.street = ?1”;
Query query = em.createQuery(jpql);
query.setParameter(1, “1 dreamland road”);
List<Employee> emps = query.getResultList();
displayQueryResult(jpql, emps);

// Perform query – Retrieve all employees who have a specific phone number
// in their contactinfo
jpql = “SELECT e FROM Employee e ”
+ “JOIN e.contactInfo.phones p WHERE p.phoneNumber = ?1”;
query = em.createQuery(jpql);
query.setParameter(1, “222-3333-3333”);
emps = query.getResultList();
displayQueryResult(jpql, emps);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);
JPAUtil.checkData(“select * from PHONE_TABLE”);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

Main.java

Summary

In this exercise,  you have explored richer mapping capabilities of JPA 2.0 through use of @ElementCollection.

 

Exercise 2: Mapping with @OrderColumn

JPA 2.0 adds support for an OrderColumn. An OrderColumn can be used to define an order List on any collection mapping. It is defined through the @OrderColumn annotation or <order-column> XML element.

The OrderColumn is maintained by the mapping and should not be an attribute of the target object. The table for the OrderColumn depends on the mapping. For a OneToMany mapping it will be in the target object’s table. For a ManyToMany mapping or a OneToMany using a JoinTable it will be in the join table. For an ElementCollection mapping it will be in the target table.

    1. Delete PHONE_TABLE manually
    2. @OrderColumn with a collection of basic type
    3. Study code
    4. @OrderColumn with one-to-many Unidirectional relationship
    5. Study code
    6. @OrderColumn with one-to-many Bidirectional relationship
    7. Study code

 

(2.0) Delete PHONE_TABLE manually (only if it exists)

The PHONE_TABLE has been created as a result of previous exercise.  In running jpa2.0_mapping_ordercolumn_ElementCollection project, which you about to run,  the persistence provider will try to delete and create EMPLOYEE table as instructed in the persistence.xml but will fail because the EMPLOYEE table has a dependency on the PHONE_TABLE table, hence the reason you will have to manually delete PHONE_TABLE first.

1. If you do not see the PHONE_TABLE, right-click on APP and select Refresh before deleting it.

  • Right click Services tab.
  • Right click APP and select Refresh.

 


Figure-2.01 – Refreshing the APP database to see the PHONE_TABLE

2. Delete PHONE_TABLE if it exists.

  • Right click PHONE_TABLE and select Delete.

 

Figure-2.02 – Deleting the PHONE_TABLE

(2.1) @OrderColumn with a collection of basic type

1. Open jpa2.0_mapping_ordercolumn_ElementCollection NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_mapping_ordercolumn_ElementCollection.
  • Click Open Project.
  • Observe that the jpa2.0_mapping_ordercolumn_ElementCollection project node appears under Projects tab window.

2. Build and run jpa2.0_mapping_ordercolumn_ElementCollection project.

  • Right-click jpa2.0_mapping_ordercolumn_ElementCollection project and select Run.
  • Observe the result in the Output window.

Figure-2.11

(2.2) Study the code

1. Employee.java

package examples.model;

import java.util.List;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OrderColumn;

@Entity
public class Employee {

@Id
@GeneratedValue
@Column(name = “EMPLOYEE_ID”)
private int id;
private String name;
private long salary;

// Collection of basic type – Stting type in this case
@ElementCollection
// Specifies a column that is used to maintain the persistent order of a list.
@OrderColumn(name=”INDEX”)
// Name the table as “phones”
@CollectionTable(name = “phones”)
private List<String> phones;

public Employee() {
}

public Employee(int id) {
this.id = id;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

@Overrride
public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}

/**
* @return the phones
*/
public List<String> getPhones() {
return phones;
}

/**
* @param phones the phones to set
*/
public void sePhones(List<String> phones) {
this.phones = phones;
}
}

2. Main.java

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityTransaction;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

Employee emp = es.createEmployee(“Sang Shin”, 10000);
List<String> phones = new ArrayList<String>();
phones.add(“111-111-1234”);
phones.add(“111-111-2345”);
phones.add(“111-111-2341”);
phones.add(“111-111-3455”);
es.setPhones(emp, phones);

emp = es.createEmployee(“Bill Clinton”, 8000);
phones = new ArrayList<String>();
phones.add(“222-222-4252”);
phones.add(“222-222-2452”);
es.setPhones(emp, phones);

es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
es.createEmployee(“Charles Lannie”, 7500);
es.createEmployee(“Shelley Nichole”, 8500);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);
JPAUtil.checkData(“select * from PHONES”);

em.close();
emf.close();

}
}

(2.3) @OrderColumn with one-to-many Unidirectional relationship

1. Open jpa2.0_mapping_ordercolumn_OneToMany_Unidirection NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_mapping_ordercolumn_OneToMany_Unidirection.
  • Click Open Project.
  • Observe that the jpa2.0_mapping_ordercolumn_OneToMany_Unidirection project node appears under Projects tab window.

2. Build and run jpa2.0_mapping_ordercolumn_OneToMany_Unidirection project.

  • Right-click jpa2.0_mapping_ordercolumn_OneToMany_Unidirection project and select Run.
  • Observe the result in the Output window.

Figure-2.31

(2.4) Study the code

1. Employee.java.

package examples.model;

import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;

@Entity
public class Employee {

@Id
@GeneratedValue
@Column(name = “EMPLOYEE_ID”)
private int id;

private String name;
private long salary;

// Unidirectional One-to-Many association using a foreign key mapping
@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
// The join column is in table for Phone (for Unidirectional relationship)
@JoinColumn(name=”EMPLOYEE_ID”)
// Specifies a column that is used to maintain the persistent order of a list.
@OrderColumn(name = “INDEX”)
private List<Phone> phones;

public Employee() {
}

public Employee(int id) {
this.id = id;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}

/**
* @return the phones
*/
public List<Phone> getPhones() {
return phones;
}

/**
* @param phones the phones to set
*/
public void sePhones(List<Phone> phones) {
this.phones = phones;
}
}

 

(2.5) @OrderColumn with one-to-many Bidirectional relationship

1. Open jpa2.0_mapping_ordercolumn_OneToMany_Bidirection NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_mapping_ordercolumn_OneToMany_Bidirection.
  • Click Open Project.
  • Observe that the jpa2.0_mapping_ordercolumn_OneToMany_Bidirection project node appears under Projects tab window.

2. Build and run jpa2.0_mapping_ordercolumn_OneToMany_Bidirection project.

  • Right-click jpa2.0_mapping_ordercolumn_OneToMany_Bidirection project and select Run.
  • Observe the result in the Output window.

Figure-2.51

(2.6) Study the code

1. Employee.java

package examples.model;

import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;

@Entity
public class Employee implements Serializable {

@Id
@GeneratedValue
@Column(name = “EMPLOYEE_ID”)
private int eid;

private String name;
private long salary;

// Bidirectional one to many relationship through “mappedBy”.
// The value of “mappedBy” is a field of Phone entity class.
@OneToMany(cascade=CascadeType.ALL, mappedBy=”employee”)
// Specifies a column that is used to maintain the persistent order of a list.
@OrderColumn(name = “INDEX”)
private List<Phone> phones;

public Employee() {
}

public Employee(int id) {
this.eid = id;
}

public int getId() {
return eid;
}

public void setId(int id) {
this.eid = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

@Override
public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}

/**
* @return the phones
*/
public List<Phone> getPhones() {
return phones;
}

/**
* @param phones the phones to set
*/
public void sePhones(List<Phone> phones) {
this.phones = phones;
}
}

Employee.java

2. Phone.java

package examples.model;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = “PHONE_TABLE”)
public class Phone implements Serializable {

@Id
@Column(name = “PHONE_ID”)
@GeneratedValue
private int id;
private String phoneNumber;

// Bi-directional one-to-many relationship
@ManyToOne(optional = false)
private Employee employee;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public Phone() {
}

public Phone(String phoneNumber, Employee emp) {
this.phoneNumber = phoneNumber;
this.employee = emp;
}

public Phone(int id, String phoneNumber) {
this.id = id;
this.phoneNumber = phoneNumber;
}

public String getPhoneNumber() {
return phoneNumber;
}

/**
* @param phoneNumber the phoneNumber to set
*/
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}

/**
* @return the employee
*/
public Employee getEmployee() {
return employee;
}

/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
}

Phone.java

3. Main.java

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import examples.model.Phone;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityTransaction;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

// Perform JPA operations
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

// Create some employees
EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

Employee emp = es.createEmployee(“Sang Shin”, 10000);
List<Phone> phones = new ArrayList<Phone>();
phones.add(new Phone(“111-111-1234”, emp));
phones.add(new Phone(“111-111-2345”, emp));
phones.add(new Phone(“111-111-2341”, emp));
phones.add(new Phone(“111-111-3455”, emp));
es.setPhones(emp, phones);
es.updateEmployee(emp);

emp = es.createEmployee(“Bill Clinton”, 8000);
phones = new ArrayList<Phone>();
phones.add(new Phone(“222-222-4252”, emp));
phones.add(new Phone(“222-222-2452”, emp));
es.setPhones(emp, phones);
es.updateEmployee(emp);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);
JPAUtil.checkData(“select * from PHONE_TABLE”);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

Main.java

Summary

In this exercise, you have explored how @OrderColumn is used to define an order List on any collection mapping.

 

Exercise 3: Map key

JPA 2.0 allows for a Map where the key is not part of the target object to be persisted. The Map key can be any of the following:

* A Basic value, stored in the target’s table or join table.
* An Embedded object, stored in the target’s table or join table.
* A foreign key to another Entity, stored in the target’s table or join table.

Map columns can be used for any collection mapping including, OneToMany, ManyToMany and ElementCollection.

 

(3.1) @MapKeyColumn

1. Open jpa2.0_mapping_MapKeyColumn NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_mapping_MapKeyColumn.
  • Click Open Project.
  • Observe that the jpa2.0_mapping_MapKeyColumn project node appears under Projects tab window.

2. Build and run jpa2.0_mapping_MapKeyColumn project.

  • Right-click jpa2.0_mapping_MapKeyColumn project and select Run.
  • Observe the result in the Output window.

Figure-3.11

(3.2) Study the code

1. Employee.java

package examples.model;

import java.io.Serializable;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MapKeyColumn;
import javax.persistence.OneToMany;

@Entity
public class Employee implements Serializable {

@Id
@GeneratedValue
@Column(name = “EMPLOYEE_ID”)
private int eid;

private String name;
private long salary;

// Bidirectional one to many relationship through “mappedBy”.
// The value of “mappedBy” is a field of Phone entity class.
@OneToMany(cascade=CascadeType.ALL, mappedBy=”employee”)
// The @MapKeyColumn annotation is used to define a map
// relationship where the key is a Basic value
@MapKeyColumn(name=”PHONE_TYPE”)
private Map<String, Phone> phones;

public Employee() {
}

public Employee(int id) {
this.eid = id;
}

public int getId() {
return eid;
}

public void setId(int id) {
this.eid = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

@Override
public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}

/**
* @return the phones
*/
public Map<String, Phone> getPhones() {
return phones;
}

/**
* @param phones the phones to set
*/
public void setPhones(Map<String, Phone> phones) {
this.phones = phones;
}

}

Employee.java

2. Phone.java

package examples.model;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = “PHONE_TABLE”)
public class Phone implements Serializable {

@Id
@Column(name = “PHONE_ID”)
@GeneratedValue
private int id;
private String phoneNumber;

// Bi-directional one-to-many relationship
@ManyToOne(optional = false)
private Employee employee;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public Phone() {
}

public Phone(String phoneNumber, Employee emp) {
this.phoneNumber = phoneNumber;
this.employee = emp;
}

public Phone(int id, String phoneNumber) {
this.id = id;
this.phoneNumber = phoneNumber;
}

public String getPhoneNumber() {
return phoneNumber;
}

/**
* @param phoneNumber the phoneNumber to set
*/
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}

/**
* @return the employee
*/
public Employee getEmployee() {
return employee;
}

/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
}

Phone.java.

3. Main.java

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import examples.model.Phone;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityTransaction;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

// Perform JPA operations
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

// Create some employees
EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

Employee emp = es.createEmployee(“Sang Shin”, 10000);
Map<String, Phone> phones = new HashMap<String, Phone>();
phones.put(“cell”, new Phone(“111-111-1234”, emp));
phones.put(“home”, new Phone(“111-111-2345”, emp));
phones.put(“fax”, new Phone(“111-111-2341”, emp));
phones.put(“cell2”, new Phone(“111-111-3455”, emp));
es.setPhones(emp, phones);
es.updateEmployee(emp);

emp = es.createEmployee(“Bill Clinton”, 8000);
phones = new HashMap<String, Phone>();
phones.put(“home”, new Phone(“222-222-4252”, emp));
phones.put(“cell”, new Phone(“222-222-2452”, emp));
es.setPhones(emp, phones);
es.updateEmployee(emp);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);
JPAUtil.checkData(“select * from PHONE_TABLE”);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

Main.java

 

(3.3) @MapKeyClass

1. Open jpa2.0_mapping_MapKeyClass NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_mapping_MapKeyClass.
  • Click Open Project.
  • Observe that the jpa2.0_mapping_MapKeyClass project node appears under Projects tab window.

2. Build and run jpa2.0_mapping_MapKeyClass project.

  • Right-click jpa2.0_mapping_MapKeyClass project and select Run.
  • Observe the result in the Output window.

Figure-3.31

(3.4) Study the code

1. Employee.java

package examples.model;

import java.io.Serializable;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MapKeyClass;
import javax.persistence.OneToMany;

@Entity
public class Employee implements Serializable {

@Id
@GeneratedValue
@Column(name = “EMPLOYEE_ID”)
private int eid;

private String name;
private long salary;

// Bidirectional one to many relationship through “mappedBy”.
// The value of “mappedBy” is a field of Phone entity class.
@OneToMany(cascade=CascadeType.ALL)
// Specifies the type of the map key for associations of type
// java.util.Map. The map key can be a basic type, an embeddable
// class, or an entity. If the map is specified using Java generics,
// the MapKeyClass annotation and associated type need not be
// specified; otherwise they must be specified.
// @MapKeyClass(PhoneType.class)  // Not needed in this case
private Map<PhoneType, Phone> phones;

public Employee() {
}

public Employee(int id) {
this.eid = id;
}

public int getId() {
return eid;
}

public void setId(int id) {
this.eid = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

@Override
public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}

/**
* @return the phones
*/
public Map<PhoneType, Phone> getPhones() {
return phones;
}

/**
* @param phones the phones to set
*/
public void setPhones(Map<PhoneType, Phone> phones) {
this.phones = phones;
}

}

Employee.java

2. Phone.java

package examples.model;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = “PHONE_TABLE”)
public class Phone implements Serializable {

@Id
@Column(name = “PHONE_ID”)
@GeneratedValue
private int id;
private String phoneNumber;

// Bi-directional one-to-many relationship
@ManyToOne(optional = false)
private Employee employee;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public Phone() {
}

public Phone(String phoneNumber) {
this.phoneNumber = phoneNumber;
}

public Phone(int id, String phoneNumber) {
this.id = id;
this.phoneNumber = phoneNumber;
}

public String getPhoneNumber() {
return phoneNumber;
}

/**
* @param phoneNumber the phoneNumber to set
*/
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}

/**
* @return the employee
*/
public Employee getEmployee() {
return employee;
}

/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
}

Phone.java

3. PhoneType.java

package examples.model;

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Embeddable;

@Embeddable
public class PhoneType implements Serializable {

@Basic
private String type;

public PhoneType() {
}

public PhoneType(String type) {
this.type = type;
}

/**
* @return the type
*/
public String getType() {
return type;
}

/**
* @param type the type to set
*/
public void setType(String type) {
this.type = type;
}

}

PhoneType.java

4. Main.java

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import examples.model.Phone;
import examples.model.PhoneType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityTransaction;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

// Perform JPA operations
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

// Create some employees
EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

Employee emp = es.createEmployee(“Sang Shin”, 10000);
Map<PhoneType, Phone> phones = new HashMap<PhoneType, Phone>();
phones.put(new PhoneType(“cell”), new Phone(“111-111-1234”, emp));
phones.put(new PhoneType(“home”), new Phone(“111-111-2345”, emp));
phones.put(new PhoneType(“fax”), new Phone(“111-111-2341”, emp));
phones.put(new PhoneType(“cell2”), new Phone(“111-111-3455”, emp));
es.setPhones(emp, phones);
es.updateEmployee(emp);

emp = es.createEmployee(“Bill Clinton”, 8000);
phones = new HashMap<PhoneType, Phone>();
phones.put(new PhoneType(“home”), new Phone(“222-222-4252”, emp));
phones.put(new PhoneType(“cell”), new Phone(“222-222-2452”, emp));
es.setPhones(emp, phones);
es.updateEmployee(emp);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);
JPAUtil.checkData(“select * from PHONE_TABLE”);
JPAUtil.checkData(“select * from EMPLOYEE_PHONE_TABLE”);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

Main.java

Summary

In this exercise, you have explored how to use different kinds of Map key.

 

Exercise 4: JPQL Impovements

JPA 2.0 have added a few new keywords such as INDEX and CASE.  The INDEX function returns an integer value corresponding to the position of its argument in an ordered list. The INDEX function can only be applied to identification variables denoting types for which an order column has been specified.

(4.1) INDEX

0. Delete EMPLOYEE_PHONE_TABLE manually.

The EMPLOYEE_PHONE_TABLE has been created as a result of previous exercise.  In running jpa2.0_jpql_index project, the persistence provider will try to delete and create EMPLOYEE table as instructed in the persistence.xml but will fail because it has a dependency on the EMPLOYEE_PHONE_TABLE, hence the reason you will have to manually delete PHONE_TABLE first.
If you do not see the EMPLOYEE_PHONE_TABLE, right-click on APP and select Refresh before deleting it.

1. Open jpa2.0_jpql_index NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_jpql_index.
  • Click Open Project.
  • Observe that the jpa2.0_jpql_index project node appears under Projects tab window.

2. Build and run jpa2.0_jpql_index project.

  • Right-click jpa2.0_jpql_index project and select Run.
  • Observe the result in the Output window.

Figure-4.11
—— Query result of “SELECT e FROM Employee e INNER JOIN e.phones p WHERE e.name = ‘Sang Shin’ AND INDEX(p) < 3 ”
Employee 1, Sang Shin, 10000
Employee 1, Sang Shin, 10000
Employee 1, Sang Shin, 10000

—— Query result of “SELECT DISTINCT e FROM Employee e INNER JOIN e.phones p WHERE e.name = ‘Sang Shin’ AND INDEX(p) < 3 ”
Employee 1, Sang Shin, 10000

—— Query result of “SELECT e FROM Employee e INNER JOIN e.phones p WHERE e.name = ‘Sang Shin’ AND INDEX(p) < 1 ”
Employee 1, Sang Shin, 10000

—— Query result of “SELECT DISTINCT e FROM Employee e INNER JOIN e.phones p WHERE INDEX(p) BETWEEN 0 AND 4 ”
Employee 1, Sang Shin, 10000
Employee 2, Bill Clinton, 8000

(4.2) Study the code

1. Main.java

@package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import examples.model.Phone;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

// Perform JPA operations
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

// Create some employees
EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

Employee emp = es.createEmployee(“Sang Shin”, 10000);
List<Phone> phones = new ArrayList<Phone>();
phones.add(new Phone(“111-111-1234”));
phones.add(new Phone(“111-111-2345”));
phones.add(new Phone(“111-111-2341”));
phones.add(new Phone(“111-111-3455”));
es.setPhones(emp, phones);

emp = es.createEmployee(“Bill Clinton”, 8000);
phones = new ArrayList<Phone>();
phones.add(new Phone(“222-222-4252”));
phones.add(new Phone(“222-222-2452”));
es.setPhones(emp, phones);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);
JPAUtil.checkData(“select * from PHONE_TABLE”);

// Usage of INDEX example
String jpql = “SELECT e ”
+ “FROM Employee e INNER JOIN e.phones p ”
+ “WHERE e.name = ‘Sang Shin’ ”
+ “AND INDEX(p) < 3 “;

Query query = em.createQuery(jpql);
List<Employee> emps = query.getResultList();
displayQueryResult(jpql, emps);

// Usage of INDEX example
jpql = “SELECT DISTINCT e ”
+ “FROM Employee e INNER JOIN e.phones p ”
+ “WHERE e.name = ‘Sang Shin’ ”
+ “AND INDEX(p) < 3 “;

query = em.createQuery(jpql);
emps = query.getResultList();
displayQueryResult(jpql, emps);

// Usage of INDEX example
jpql = “SELECT e ”
+ “FROM Employee e INNER JOIN e.phones p ”
+ “WHERE e.name = ‘Sang Shin’ ”
+ “AND INDEX(p) < 1 “;

query = em.createQuery(jpql);
emps = query.getResultList();
displayQueryResult(jpql, emps);

// Usage of INDEX example
jpql = “SELECT DISTINCT e ”
+ “FROM Employee e INNER JOIN e.phones p ”
+ “WHERE INDEX(p) BETWEEN 0 AND 4 “;

query = em.createQuery(jpql);
emps = query.getResultList();
displayQueryResult(jpql, emps);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

Main.java

 

(4.3) CASE

1. Open jpa2.0_jpql_case NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_jpql_case.
  • Click Open Project.
  • Observe that the jpa2.0_jpql_case project node appears under Projects tab window.

2. Build and run jpa2.0_jpql_case project.

  • Right-click jpa2.0_jpql_case project and select Run.
  • Observe the result in the Output window.

Figure-4.31

(4.4) Study the code

1. Main.java.

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.EmployeeService;

import javax.persistence.Query;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

em.getTransaction().begin();
es.createEmployee(“Sang Shin”, 10000);
es.createEmployee(“Bill Clinton”, 8000);
es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
em.getTransaction().commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);

// Use CASE
String jpql = “UPDATE Employee e SET e.salary = ” +
“CASE WHEN e.salary > 9000 THEN e.salary * 1.10 ” +
”     WHEN e.salary > 7500 THEN e.salary * 1.08 ” +
”     ELSE e.salary * 0.95 ” +
“END” ;
Query q = em.createQuery(jpql);

em.getTransaction().begin();
int updated = q.executeUpdate();
em.getTransaction().commit();
displayQueryResult(jpql, updated);

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, int deleted) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
System.out.println(“Number of updated records ” + deleted);
}
}

Main.java

Summary

In this exercise,  you have explored some new keywords that are added to JPQL, especially INDEX and CASE.

 

Exercise 5: Criteria API (without using Metamodel)

The Java Persistence Criteria API is used to define queries through the construction of object-based query definition objects, rather than use of the string-based approach of the Java Persistence query language, thus providing  type-safe, and portable queries that work regardless of the underlying data store.

The Criteria API and JPQL are closely related, and designed to allow similar operations in their queries. Developers familiar with JPQL syntax will find equivalent object-level operations in the Criteria API.

The basic semantics of a Criteria query consists of a select clause, a from clause, and an optional where clause, similar to a JPQL query. Criteria queries set these clauses using Java programming language objects, so the query can be created in a type-safe manner.

 Please read Basic Type-Safe Queries Using the Criteria API and Metamodel API section of the Java EE 6 tutorial before you do this exercise.

 

(5.1) Criteria API with “where” method

0. Delete PHONE_TABLE and EMPLOYEE tables.

1. Open jpa2.0_criteria_where NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_criteria_where.
  • Click Open Project.
  • Observe that the jpa2.0_criteria_where project node appears under Projects tab window.

2. Build and run jpa2.0_criteria_where project.

  • Right-click jpa2.0_criteria_where project and select Run.
  • Observe the result in the Output window.

Figure-5.11

—— Query result of “SELECT e FROM Employee e”
Employee 3, Angela Caicedo, 6000
Employee 5, Charles Song, 4500
Employee 1, Sang Shin, 10000
Employee 4, Annie Song, 5000
Employee 2, Bill Clinton, 8000

******* Query result using Criteria API
Employee 3, Angela Caicedo, 6000
Employee 5, Charles Song, 4500
Employee 1, Sang Shin, 10000
Employee 4, Annie Song, 5000
Employee 2, Bill Clinton, 8000

—— Query result of “SELECT e FROM Employee e where e.name = ‘Sang Shin'”
Employee 1, Sang Shin, 10000

******* Query result using Criteria API
Employee 1, Sang Shin, 10000

—— Query result of “SELECT e FROM Employee e where e.name = ‘Sang Shin’ OR e.salary > 7000”
Employee 1, Sang Shin, 10000
Employee 2, Bill Clinton, 8000

******* Query result using Criteria API
Employee 1, Sang Shin, 10000
Employee 2, Bill Clinton, 8000

—— Query result of “SELECT e FROM Employee e where e.name LIKE ‘A%'”
Employee 3, Angela Caicedo, 6000
Employee 4, Annie Song, 5000

******* Query result using Criteria API
Employee 3, Angela Caicedo, 6000
Employee 4, Annie Song, 5000

—— Query result of “SELECT e FROM Employee e where e.name IN (‘Sang Shin’, ‘Bill Clinton’, ‘Some name’)”
Employee 1, Sang Shin, 10000
Employee 2, Bill Clinton, 8000

******* Query result using Criteria API
Employee 1, Sang Shin, 10000

(5.2) Study code

1. Main.java

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

em.getTransaction().begin();
es.createEmployee(“Sang Shin”, 10000);
es.createEmployee(“Bill Clinton”, 8000);
es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
es.createEmployee(“Charles Song”, 4500);
em.getTransaction().commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);

// Get all employees whose name is ‘Sang Shin’
String jpql = “SELECT e FROM Employee e”;
List<Employee> emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
CriteriaBuilder cbuilder = em.getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<Employee> criteria = cbuilder.createQuery(Employee.class);
Root<Employee> employee = criteria.from(Employee.class);

// —- Build criteria
criteria.select(employee);

// —- Create a query object from Criteria and perform query operation
//TypedQuery<Employee> q = em.createQuery(criteria);
//emps = q.getResultList();
emps = em.createQuery(criteria).getResultList();

// —- Display the result
displayQueryResult2(emps);

// Get all employees whose name is ‘Sang Shin’
jpql = “SELECT e FROM Employee e where e.name = ‘Sang Shin'”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API

// —- Build criteria
criteria.select(employee);
criteria.where(cbuilder.equal(employee.get(“name”), “Sang Shin”));

// —- Create a query object from Criteria and perform query operation
emps = em.createQuery(criteria).getResultList();

// —- Display the result
displayQueryResult2(emps);

// Get all employees whose name is ‘Sang Shin’ or whose salary is greater than 7000
jpql = “SELECT e FROM Employee e where e.name = ‘Sang Shin’ OR e.salary > 7000”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
criteria.select(employee);
criteria.where(cbuilder.or(cbuilder.equal(employee.get(“name”), “Sang Shin”), cbuilder.greaterThan(employee.get(“salary”).as(Integer.class), 7000)));
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

// Get all emplyees whose name starts with A
jpql = “SELECT e FROM Employee e where e.name LIKE ‘A%'”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
criteria.select(employee);
criteria.where(cbuilder.like(employee.get(“name”).as(String.class),  “A%”));
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

// Get all employees whose name is either ‘Sang Shin’ or ‘Bill Clinton” or ‘Some name’
jpql = “SELECT e FROM Employee e where e.name IN (‘Sang Shin’, ‘Bill Clinton’, ‘Some name’)”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
criteria.select(employee);
criteria.where(employee.get(“name”).in(“Sang Shin”, “Bill Clinton”, “Some name”));
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}

// Display the query result
public static void displayQueryResult2(List<Employee> emps) {
System.out.println(“\n******* Query result using Criteria API”);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

2. Display and study Javadoc of CriteriaQuery.

(5.3) Criteria API with “orderBy” method

1. Open jpa2.0_criteria_order_by NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_criteria_order_by.
  • Click Open Project.
  • Observe that the jpa2.0_criteria_order_by project node appears under Projects tab window.

2. Build and run jpa2.0_criteria_order_by project.

  • Right-click jpa2.0_criteria_order_by project and select Run.
  • Observe the result in the Output window.

Figure-5.31

(5.4) Study code

1. Main.java.

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import java.util.List;
import javax.persistence.EntityTransaction;

import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

EntityTransaction tx = em.getTransaction();
tx.begin();

es.createEmployee(“Sang Shin”, 10000);
es.createEmployee(“Bill Clinton”, 8000);
es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
es.createEmployee(“Charles Lannie”, 7500);
es.createEmployee(“Shelley Nichole”, 8500);

tx.commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);

// Perform JPA query with ORDER BY
String jpql = “SELECT e FROM Employee e ”
+ “WHERE e.salary > 4000 ”
+ “ORDER BY e.name ASC, e.salary DESC”;
Query q = em.createQuery(jpql);
List<Employee> emps = q.getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
CriteriaBuilder cbuilder = em.getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<Employee> criteria = cbuilder.createQuery(Employee.class);
Root<Employee> employee = criteria.from(Employee.class);

// Create criteria
criteria.select(employee);
criteria.where(cbuilder.or(cbuilder.equal(employee.get(“name”), “Sang Shin”), cbuilder.greaterThan(employee.get(“salary”).as(Integer.class), 4000)));
criteria.orderBy(cbuilder.asc(employee.get(“name”)), cbuilder.desc(employee.get(“salary”)));

// Create query using Criteria and then perform query operation
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}

// Display the query result
public static void displayQueryResult2(List<Employee> emps) {
System.out.println(“\n******* Query result using Criteria API”);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

Main.java

 

(5.5) Criteria API with relationship traversal

1. Open jpa2.0_criteria_relation_traversal NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_criteria_relation_traversal.
  • Click Open Project.
  • Observe that the jpa2.0_criteria_relation_traversal project node appears under Projects tab window.

2. Build and run jpa2.0_criteria_relation_traversal project.

  • Right-click jpa2.0_criteria_relation_traversal project and select Run.
  • Observe the result in the Output window.

Figure-5.51

(5.6) Study code

1. Main.java.

package mypackage;

import customer.model.Customer;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import java.util.List;

import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“CustomerServicePU”);
EntityManager em = emf.createEntityManager();

// Display the test table
JPAUtil.checkData(“select CUSTOMER_ID, DISCOUNT_CODE, NAME, EMAIL from CUSTOMER”);
JPAUtil.checkData(“select * from DISCOUNT_CODE”);

// Display all customers whose discount rate is bigger than 10%
String jpql = “SELECT c FROM Customer c WHERE c.discountCode.rate > 10”;
Query query = em.createQuery(jpql);
List<Customer> customers = query.getResultList();
displayQueryResult(jpql, customers);

///////// Perform the same query using Criteria API
CriteriaBuilder cbuilder = em.getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<Customer> criteria = cbuilder.createQuery(Customer.class);
Root<Customer> Customer = criteria.from(Customer.class);

// Create criteria
criteria.select(Customer);
criteria.where(cbuilder.greaterThan(Customer.get(“discountCode”).get(“rate”).as(Integer.class), 10));

// Create query using Criteria and then perform query operation
customers = em.createQuery(criteria).getResultList();
displayQueryResult2(customers);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Customer> customers) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Customer e : customers) {
System.out.println(“Customer id = ” + e.getCustomerId() + “, name = ” + e.getName() + “, discount rate = ” + e.getDiscountCode().getRate());
}
}

// Display the query result
public static void displayQueryResult2(List<Customer> customers) {
System.out.println(“\n******* Query result using Criteria API”);
for (Customer e : customers) {
System.out.println(“Customer id = ” + e.getCustomerId() + “, name = ” + e.getName() + “, discount rate = ” + e.getDiscountCode().getRate());
}
}
}

(5.7) Criteria API with inner join

1. Open jpa2.0_criteria_relation_innerjoin NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_criteria_relation_innerjoin.
  • Click Open Project.
  • Observe that the jpa2.0_criteria_relation_innerjoin project node appears under Projects tab window.

2. Build and run jpa2.0_criteria_relation_innerjoin project.

  • Right-click jpa2.0_criteria_relation_innerjoin project and select Run.
  • Observe the result in the Output window.

Figure-5.71

(5.8) Study code

1. Main.java.

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import java.util.List;

import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Root;
import product.client.Manufacturer;
import product.client.Product;
import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

// Display the test table
JPAUtil.checkData(“select MANUFACTURER_ID, NAME, CITY from MANUFACTURER”);
//JPAUtil.checkData(“select * from MANUFACTURER”);
JPAUtil.checkData(“select PRODUCT_ID, MANUFACTURER_ID, MARKUP, DESCRIPTION from PRODUCT”);
//JPAUtil.checkData(“select * from PRODUCT”);
JPAUtil.checkData(“select * from PRODUCT_CODE”);

// Perform JPA operations
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“ManufacturerServicePU”);
EntityManager em = emf.createEntityManager();

// Display all manufacturers who have products whose markups are greater than 20.0 – same as above
String jpql = “SELECT m FROM Manufacturer m ”
+ “INNER JOIN m.productCollection p WHERE p.markup > 20.0”;
Query query = em.createQuery(jpql);
List<Manufacturer> manufacturers = query.getResultList();
displayQueryResult(jpql, manufacturers);

///////// Perform the same query using Criteria API
CriteriaBuilder cbuilder = em.getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<Manufacturer> criteria = cbuilder.createQuery(Manufacturer.class);
Root<Manufacturer> m = criteria.from(Manufacturer.class);
Join<Manufacturer, Product> p = m.join(“productCollection”);

// Create criteria
criteria.select(m);
criteria.where(cbuilder.greaterThan(p.get(“markup”).as(Integer.class), 20));

// Create query using Criteria and then perform query operation
manufacturers = em.createQuery(criteria).getResultList();
displayQueryResult2(manufacturers);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Manufacturer> manufacturers) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Manufacturer e : manufacturers) {
System.out.println(“Manufacturer id = ” + e.getManufacturerId() + “, name = ” + e.getName() + “, Sales rep = ” + e.getRep() );
}
}

// Display the query result
public static void displayQueryResult2(List<Manufacturer> manufacturers) {
System.out.println(“\n******* Query result using Criteria API”);
for (Manufacturer e : manufacturers) {
System.out.println(“Manufacturer id = ” + e.getManufacturerId() + “, name = ” + e.getName() + “, Sales rep = ” + e.getRep() );
}
}

}

Main.java

Summary

In this exercise,  you have explored how to use Criteria API to define queries through the construction of object-based query definition objects, rather than use of the string-based approach of the Java Persistence query language, thus providing  type-safe, and portable queries that work regardless of the underlying data store.

Exercise 6: Criteria API (using Metamodel)

A metamodel class describes the meta information of a persistent class. A metamodel class is canonical if the class describes the meta information of a persistent entity in the exact manner stipulated by the JPA 2.0 specification. A canonical metamodel class is static in the sense all its member variables are declared static (and public). The Person_.age is one such static member variable. You instantiate the canonical class by generating a concrete Person_.java at a source-code level at development time. Through such instantiation, it is possible to refer to persistent attributes of Person at compile time, rather than at run time, in a strongly typed manner.

This Person_ metamodel class is an alternative means of referring to meta information of Person. This alternative is similar to the much-used (some may say, abused) Java Reflection API, but with a major conceptual difference. You can use reflection to obtain the meta information about an instance of a java.lang.Class, but meta information about Person.class cannot be referred to in a way that a compiler can verify. For example, using reflection, you’d refer to the field named age in Person.class with:

 

(6.1) Open, build, and run “jpa2.0_criteria_where_metamodel1_getMetaModel” sample application

1. Open jpa2.0_criteria_where_metamodel1_getMetaModel NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_criteria_where_metamodel1_getMetaModel.
  • Click Open Project.
  • Observe that the jpa2.0_criteria_where_metamodel1_getMetaModel project node appears under Projects tab window.

2. Build and run jpa2.0_criteria_where_metamodel1_getMetaModel project.

  • Right-click jpa2.0_criteria_where_metamodel1_getMetaModel project and select Run.
  • Observe the result in the Output window.  Note that this is the same result you see when you ran jpa2.0_criteria_where project.

Figure-6.11

(6.2) Study code

1. Main.java

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;

import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

em.getTransaction().begin();
es.createEmployee(“Sang Shin”, 10000);
es.createEmployee(“Bill Clinton”, 8000);
es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
es.createEmployee(“Charles Song”, 4500);
em.getTransaction().commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);

// Get all employees whose name is ‘Sang Shin’
String jpql = “SELECT e FROM Employee e”;
List<Employee> emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
CriteriaBuilder cbuilder = em.getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<Employee> criteria = cbuilder.createQuery(Employee.class);

// Use Metamodel – Obtaining a Metamodel Class Dynamically Using the Metamodel.getMetamodel Method
Metamodel m = em.getMetamodel();
EntityType<Employee> Employee_ = m.entity(Employee.class);
Root<Employee> employee = criteria.from(Employee_);
//Root<Employee> employee = criteria.from(Employee.class);

// —- Build criteria
criteria.select(employee);

// —- Create a query object from Criteria and perform query operration
//TypedQuery<Employee> q = em.createQuery(criteria);
//emps = q.getResultList();
emps = em.createQuery(criteria).getResultList();

// —- Display the result
displayQueryResult2(emps);

// Get all employees whose name is ‘Sang Shin’
jpql = “SELECT e FROM Employee e where e.name = ‘Sang Shin'”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API

// —- Build criteria
criteria.select(employee);
criteria.where(cbuilder.equal(employee.get(“name”), “Sang Shin”));

// —- Create a query object from Criteria and perform query operration
emps = em.createQuery(criteria).getResultList();

// —- Display the result
displayQueryResult2(emps);

// Get all employees whose name is ‘Sang Shin’ or whose salary is greater than 7000
jpql = “SELECT e FROM Employee e where e.name = ‘Sang Shin’ OR e.salary > 7000”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
criteria.select(employee);
criteria.where(cbuilder.or(cbuilder.equal(employee.get(“name”), “Sang Shin”), cbuilder.greaterThan(employee.get(“salary”).as(Integer.class), 7000)));
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

// Get all emplyees whose name starts with A
jpql = “SELECT e FROM Employee e where e.name LIKE ‘A%'”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
criteria.select(employee);
criteria.where(cbuilder.like(employee.get(“name”).as(String.class), “A%”));
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

// Get all employees whose name is either ‘Sang Shin’ or ‘Bill Clinton” or ‘Some name’
jpql = “SELECT e FROM Employee e where e.name IN (‘Sang Shin’, ‘Bill Clinton’, ‘Some name’)”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
criteria.select(employee);
criteria.where(employee.get(“name”).in(“Sang Shin”, “Bill Clinton”, “Some name”));
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}

// Display the query result
public static void displayQueryResult2(List<Employee> emps) {
System.out.println(“\n******* Query result using Criteria API”);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

Main.java

(6.3) Open, build, and run “jpa2.0_criteria_where_metamodel2_Root_getModel” sample application

1. Open jpa2.0_criteria_where_metamodel2_Root_getModel NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_criteria_where_metamodel2_Root_getModel.
  • Click Open Project.
  • Observe that the jpa2.0_criteria_where_metamodel2_Root_getModel project node appears under Projects tab window.

2. Build and run jpa2.0_criteria_where_metamodel2_Root_getModel project.

  • Right-click jpa2.0_criteria_where_metamodel2_Root_getModel project and select Run.
  • Observe the result in the Output window.  Note that this is the same result you see when you ran jpa2.0_criteria_where project.

Figure-6.31

(6.4) Study code

1. Main.java

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;

import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

em.getTransaction().begin();
es.createEmployee(“Sang Shin”, 10000);
es.createEmployee(“Bill Clinton”, 8000);
es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
es.createEmployee(“Charles Song”, 4500);
em.getTransaction().commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);

// Get all employees whose name is ‘Sang Shin’
String jpql = “SELECT e FROM Employee e”;
List<Employee> emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
CriteriaBuilder cbuilder = em.getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<Employee> criteria = cbuilder.createQuery(Employee.class);

// Use Metamodel – Obtaining a Metamodel Class Dynamically Using the Root<T>.getModel Method
Root<Employee> employee = criteria.from(Employee.class);
EntityType<Employee> Employee_ = employee.getModel();
employee = criteria.from(Employee_);

// —- Build criteria
criteria.select(employee);

// —- Create a query object from Criteria and perform query operration
//TypedQuery<Employee> q = em.createQuery(criteria);
//emps = q.getResultList();
emps = em.createQuery(criteria).getResultList();

// —- Display the result
displayQueryResult2(emps);

// Get all employees whose name is ‘Sang Shin’
jpql = “SELECT e FROM Employee e where e.name = ‘Sang Shin'”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API

// —- Build criteria
criteria.select(employee);
criteria.where(cbuilder.equal(employee.get(“name”), “Sang Shin”));

// —- Create a query object from Criteria and perform query operration
emps = em.createQuery(criteria).getResultList();

// —- Display the result
displayQueryResult2(emps);

// Get all employees whose name is ‘Sang Shin’ or whose salary is greater than 7000
jpql = “SELECT e FROM Employee e where e.name = ‘Sang Shin’ OR e.salary > 7000”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
criteria.select(employee);
criteria.where(cbuilder.or(cbuilder.equal(employee.get(“name”), “Sang Shin”), cbuilder.greaterThan(employee.get(“salary”).as(Integer.class), 7000)));
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

// Get all emplyees whose name starts with A
jpql = “SELECT e FROM Employee e where e.name LIKE ‘A%'”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
criteria.select(employee);
criteria.where(cbuilder.like(employee.get(“name”).as(String.class), “A%”));
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

// Get all employees whose name is either ‘Sang Shin’ or ‘Bill Clinton” or ‘Some name’
jpql = “SELECT e FROM Employee e where e.name IN (‘Sang Shin’, ‘Bill Clinton’, ‘Some name’)”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

///////// Perform the same query using Criteria API
criteria.select(employee);
criteria.where(employee.get(“name”).in(“Sang Shin”, “Bill Clinton”, “Some name”));
emps = em.createQuery(criteria).getResultList();
displayQueryResult2(emps);

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}

// Display the query result
public static void displayQueryResult2(List<Employee> emps) {
System.out.println(“\n******* Query result using Criteria API”);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

Main.java

Summary

In this exercise,  you have explored how to use Criteria API with metamodel class.

 

Exercise 7: Locking

Optimistic locking lets concurrent transactions process simultaneously, but detects and prevent collisions, this works best for applications where most concurrent transactions do not conflict. JPA Optimistic locking allows anyone to read and update an entity, however a version check is made upon commit and an exception is thrown if the version was updated in the database since the entity was read.  In JPA for Optimistic locking you annotate an attribute with @Version.

The Version attribute will be incremented with a successful commit. The Version attribute can be an int, short, long, or timestamp.

Pessimistic concurrency locks the database row when data is read, this is the equivalent of a (SELECT . . . FOR UPDATE [NOWAIT]) .  Pessimistic locking ensures that transactions do not update the same entity at the same time, which can simplify application code, but it limits concurrent access to the data which can cause bad scalability and may cause deadlocks. Pessimistic locking is better for applications with a higher risk of contention among concurrent transactions.

(7.1) Open, build, and run “locking” sample application (from “glassfish-samples”)

1. Open locking NetBeans project (from “glassfish samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <GlassFish-v3-Installation-Directory>/glassfish/samples/javaee6/jpa directory directory.
  • Select locking.
  • Click Open Project.


Figure-7.11

  • Observe that the locking project node appears under Projects tab window.

2. Check the path to your server application installation.

  • Browse to <GlassFish-v3-Installation-Directory>/glassfish/samples/bp-project directory and
    open build.properties file with a text editor.
  • Check that in the second line javaee.home is set to the directory where GlassFish is installed.
    For example, on a standard Mac OS X installation, it should be set to: /Applications/NetBeans

3. Build and run locking project.

  • Right-click locking project and select Run.
  • Observe the result in the Output window.
locking-test.runjavaclient:
LockingJavaClient: Test is starting
Calling URL:http://localhost:8080/locking/test/?tc=initData&nc=6&ns=3&np=3

Starting parallel updates with 9 users for operation: updateWOL
Calling URL:http://localhost:8080/locking/test/?tc=updateWOL&uid=1
Calling URL:http://localhost:8080/locking/test/?tc=updateWOL&uid=3
Calling URL:http://localhost:8080/locking/test/?tc=updateWOL&uid=5
Calling URL:http://localhost:8080/locking/test/?tc=updateWOL&uid=8
Calling URL:http://localhost:8080/locking/test/?tc=updateWOL&uid=6
Calling URL:http://localhost:8080/locking/test/?tc=updateWOL&uid=4
Calling URL:http://localhost:8080/locking/test/?tc=updateWOL&uid=2
Calling URL:http://localhost:8080/locking/test/?tc=updateWOL&uid=9
Calling URL:http://localhost:8080/locking/test/?tc=updateWOL&uid=7
Result for operation updateWOL for userId 6 is Success
Result for operation updateWOL for userId 8 is Success
Result for operation updateWOL for userId 3 is Success
Result for operation updateWOL for userId 5 is Failure
Result for operation updateWOL for userId 9 is Success
Result for operation updateWOL for userId 1 is Failure
Result for operation updateWOL for userId 4 is Success
Result for operation updateWOL for userId 7 is Success
Result for operation updateWOL for userId 2 is Failure
Parallel updates executed with 9 users for operation: updateWOL Time taken:7630 miliseconds

Starting parallel updates with 9 users for operation: updateWPL
Calling URL:http://localhost:8080/locking/test/?tc=updateWPL&uid=1
Calling URL:http://localhost:8080/locking/test/?tc=updateWPL&uid=3
Calling URL:http://localhost:8080/locking/test/?tc=updateWPL&uid=5
Calling URL:http://localhost:8080/locking/test/?tc=updateWPL&uid=7
Calling URL:http://localhost:8080/locking/test/?tc=updateWPL&uid=9
Calling URL:http://localhost:8080/locking/test/?tc=updateWPL&uid=8
Calling URL:http://localhost:8080/locking/test/?tc=updateWPL&uid=2
Calling URL:http://localhost:8080/locking/test/?tc=updateWPL&uid=6
Calling URL:http://localhost:8080/locking/test/?tc=updateWPL&uid=4
Result for operation updateWPL for userId 7 is Success
Result for operation updateWPL for userId 9 is Success
Result for operation updateWPL for userId 4 is Success
Result for operation updateWPL for userId 6 is Success
Result for operation updateWPL for userId 5 is Success
Result for operation updateWPL for userId 3 is Success
Result for operation updateWPL for userId 1 is Success
Result for operation updateWPL for userId 8 is Success
Result for operation updateWPL for userId 2 is Success
Parallel updates executed with 9 users for operation: updateWPL Time taken:11625 miliseconds
LockingJavaClient: Test is ended


Figure-7.12

Figure-7.13

(7.2) Study the code

1. Part.java

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only (“GPL”) or the Common Development
* and Distribution License(“CDDL”) (collectively, the “License”).  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the “Classpath” exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: “Portions Copyrighted [year]
* [name of copyright owner]”
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding “[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license.”  If you don’t indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package enterprise.locking.entity;

import javax.persistence.*;
import java.util.Set;

@Entity
@Table(name = “T_PART”)
public class Part implements java.io.Serializable {

// Instance variables
private int id;
private String name;
private int amount;
private int verNum;
private Set<User> users;

public Part() {
}

public Part(int id, String name) {
this.id = id;
this.name = name;
}

public Part(int id, String name, int amount) {
this.id = id;
this.name = name;
this.amount = amount;
}

// ==================================================
// getters and setters for the state fields

@Id
@Column(name = “PID”)
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

@Column(length = 20, name = “PNAME”)
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Column(name = “AMOUNT”)
public int getAmount() {
return amount;
}

public void setAmount(int amount) {
this.amount = amount;
}

@Version
@Column(name = “VER”)
public int getVerNum() {
return verNum;
}

public void setVerNum(int verNum) {
this.verNum = verNum;
}

// ===========================================================
// getters and setters for the association fields
@OneToMany(cascade = CascadeType.ALL, mappedBy = “part”)
public Set<User> getUsers() {
return users;
}

public void setUsers(Set<User> users) {
this.users = users;
}

public String toString() {
return “Product id=” + getId() + “, amount=” + getAmount();
}

}

enterprise.locking.entity.Part.java


Figure-7.21


Figure-7.22

2. User.java

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only (“GPL”) or the Common Development
* and Distribution License(“CDDL”) (collectively, the “License”).  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the “Classpath” exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: “Portions Copyrighted [year]
* [name of copyright owner]”
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding “[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license.”  If you don’t indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package enterprise.locking.entity;

import javax.persistence.*;

@Entity
@Table(name = “T_USER”)
public class User implements java.io.Serializable {
public enum UserType {
CONSUMER, SUPPLIER
}

private int id;
private String firstName;
private String lastName;
private UserType userType;
private int count;
private Part part;

public User() {
}

public User(int id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}

public User(int id, String firstName, String lastName, UserType userType) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.userType = userType;
}

//=======================================================
// getters and setters for the state fields
@Id
@Column(name = “UID”)
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

@Column(length = 20, name = “FNAME”)
public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

@Column(length = 20, name = “LNAME”)
public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

@Column(name = “UTYPE”)
public UserType getUserType() {
return userType;
}

public void setUserType(UserType userType) {
this.userType = userType;
}

@Column(name = “COUNT”)
public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

// ===========================================================
// getters and setters for the association fields
@ManyToOne
@JoinColumn(name = “PID”)
public Part getPart() {
return part;
}

public void setPart(Part part) {
this.part = part;
}

public String toString() {
return “User id=” + getId()
+ “, lastName=” + getLastName()
+ “, userType=” + getUserType();
}

}

User.java

3. StatelessSessionBean.java

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only (“GPL”) or the Common Development
* and Distribution License(“CDDL”) (collectively, the “License”).  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the “Classpath” exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: “Portions Copyrighted [year]
* [name of copyright owner]”
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding “[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license.”  If you don’t indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package enterprise.locking.ejb;

import enterprise.locking.entity.Part;
import enterprise.locking.entity.User;

import javax.ejb.Stateless;
import javax.persistence.*;
import java.util.Random;

@Stateless
public class StatelessSessionBean {

@PersistenceContext
private EntityManager em;

private String name = “foo”;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

/**
* Initializes data for given number of consumers, suppliers and parts
*/
public void initData(int numberOfConsumers, int numberOfSuppliers, int numberOfParts) {
// user info
int uid = 0;
String fName = null;
String lName = null;
User u = null;
int pid = 0;
String pName = null;
Part p = null;
Part partRef[] = new Part[numberOfParts];

for (int i = 0; i < numberOfParts; i++) {
pid++;
pName = “p” + pid;
p = new Part(pid, pName);
p.setAmount(500);
partRef[i] = p;
em.persist(p);
}

int partIndex = 1;
Random randomGenerator = new Random();
for (int i = 0; i < numberOfConsumers; i++) {
uid++;
fName = “f” + uid;
lName = “l” + uid;
u = new User(uid, fName, lName);
u.setUserType(User.UserType.CONSUMER);
u.setCount(2);
// randam int from 0, …, NT-1
partIndex = randomGenerator.nextInt(numberOfParts);
u.setPart(partRef[partIndex]);
em.persist(u);
}

for (int i = 0; i < numberOfSuppliers; i++) {
uid++;
fName = “f” + uid;
lName = “l” + uid;
u = new User(uid, fName, lName);
u.setUserType(User.UserType.SUPPLIER);
u.setCount(10);
partIndex = randomGenerator.nextInt(numberOfParts);
u.setPart(partRef[partIndex]);
em.persist(u);
}
}

/**
* A find followed by some think time, followed by update.
*/
public boolean updateWithOptimisticLock(int uID, int s) {
boolean updateSuccessfull = true;
User u = em.find(User.class, uID);
int pID = u.getPart().getId();
Part p = em.find(Part.class, pID);

// Simulate think time to allow parallel threads to find Usrs in parallel.
simulateThinkTimeForSecond(s);
int uCount = u.getCount();
int pAmount = p.getAmount();
// update part
if (u.getUserType() == User.UserType.CONSUMER) {
p.setAmount(pAmount – uCount);
} else {
p.setAmount(pAmount + uCount);
}

try {
em.flush();
} catch (OptimisticLockException e) {
System.out.println(“Got OptimisticLockException while updating with Optimistic Lock. ” +
“The transaction will be rolled back”);
updateSuccessfull = false;
} catch (PersistenceException e ) {
System.out.println(“Got Exception while updating with optimstic lock” + e);
updateSuccessfull = false;
}
return updateSuccessfull;
}

/**
* A find with pessimistic lock followed by some think time, followed by update.
*/
public boolean updateWithPessimisticLock(int uID, int s) {
boolean updateSuccessfull = true;

User u = em.find(User.class, uID);
int pID = u.getPart().getId();
// Using Pessimistic lock to find the part object.
Part p = em.find(Part.class, pID, LockModeType.PESSIMISTIC_WRITE);

// Simulate think time to allow parallel threads to find in parallel.
simulateThinkTimeForSecond(s);
int uCount = u.getCount();
int pAmount = p.getAmount();
// update part
if (u.getUserType() == User.UserType.CONSUMER) {
p.setAmount(pAmount – uCount);
} else {
p.setAmount(pAmount + uCount);
}

try {
em.flush();
} catch (PersistenceException e) {
updateSuccessfull = false;
}
return updateSuccessfull;

}

public void simulateThinkTimeForSecond(int sec) {
//TODO check if sleep is allowed by EE spec
try {
Thread.sleep(sec * 1000);
} catch (Exception ex) {
System.out.println(“get exp in sleep”);
}
}

}

StatelessSessionBean.java

Summary

In this exercise,  you have experimented with both optimistic locking and pessimistic locking.

 

 

Exercise 8: Caching API

JPA 1.0 did not specify support of a second level cache, however, most of the persistence providers provided support for second level cache(s). JPA 2.0 specifies support for basic cache operations with the new Cache API, which is accessible from the EntityManagerFactory.

  1. Open, build, and run “jpa2.0_cache” sample application
  2. Study code

(8.1) Open, build, and run “jpa2.0_cache” sample application

1. Open jpa2.0_cache NetBeans project (from “Lab samples”).

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <LAB_UNZIPPED_DIRECTORY>/javaee6_jpa2.0/samples directory.
  • Select jpa2.0_cache.
  • Click Open Project.
  • Observe that the jpa2.0_cache project node appears under Projects tab window.

2. Build and run jpa2.0_cache project.

  • Right-click jpa2.0_cache project and select Run.
  • Observe the result in the Output window.

Figure-8.11

(8.2) Study code

1. Main.java.

package mypackage;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import examples.model.Employee;
import examples.model.EmployeeService;
import java.util.List;
import javax.persistence.Cache;

import util.JPAUtil;

public class Main {

public static void main(String[] args) throws Exception {

EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“EmployeeService”);
EntityManager em = emf.createEntityManager();

EmployeeService es = new EmployeeService(em);

em.getTransaction().begin();
es.createEmployee(“Sang Shin”, 10000);
es.createEmployee(“Bill Clinton”, 8000);
es.createEmployee(“Angela Caicedo”, 6000);
es.createEmployee(“Annie Song”, 5000);
es.createEmployee(“Charles Song”, 4500);
em.getTransaction().commit();

// Display the table
JPAUtil.checkData(“select * from EMPLOYEE”);

// Get all employees whose name is ‘Sang Shin’
String jpql = “SELECT e FROM Employee e”;
List<Employee> emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

// Get all employees whose name is ‘Sang Shin’
jpql = “SELECT e FROM Employee e where e.name = ‘Sang Shin'”;
emps = em.createQuery(jpql).getResultList();
displayQueryResult(jpql, emps);

// Perform cache operations
Cache cache = emf.getCache();
System.out.println(“cache.contains(Employee.class, 100) = ” + cache.contains(Employee.class, 100)); // false
System.out.println(“cache.contains(Employee.class, 1) before evict = ” + cache.contains(Employee.class, 1));  // true
cache.evict(Employee.class, 1);
System.out.println(“cache.contains(Employee.class, 1) after evict = ” + cache.contains(Employee.class, 1)); // false

em.close();
emf.close();

}

// Display the query result
public static void displayQueryResult(String jpql, List<Employee> emps) {
System.out.println(“\n—— Query result of \”” + jpql + “\””);
for (Employee e : emps) {
System.out.println(“Employee ” + e.getId() + “, ” + e.getName() + “, ” + e.getSalary());
}
}
}

Main.java

2. Employee.java

package examples.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.eclipse.persistence.annotations.Cache;
import org.eclipse.persistence.annotations.CacheType;

@Entity
@Cache(type=CacheType.FULL)
public class Employee {
@Id
@GeneratedValue
@Column(name=”EMPLOYEE_ID”)
private int id;
private String name;
private long salary;

public Employee() {}
public Employee(int id) {
this.id = id;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public long getSalary() {
return salary;
}

public void setSalary(long salary) {
this.salary = salary;
}

@Overrride
public String toString() {
return “Employee id: ” + getId() + ” name: ” + getName() + ” salary: ” + getSalary();
}
}

Employee.java

Summary

In this exercise,  you have explored with newly introduced Caching API.

Exercise 9: Build and run “order” sample application (from “Java EE 6 tutorial”)

In this exercise, you are going to build and run “order” sample application from Java EE 6 tutorial.  For detailed description of this example, please see “The order Application” section of the tutorial.

 

(9.1) Open, build, and run “order” sample application (from “Java EE 6 tutorial”)

1. Open order NetBeans project.

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <GlassFish-v3-Installation-Directory>/glassfish/docs/javaee-tutorial/examples/persistence directory.  (This is “Java EE 6 tutorial” examples.)
  • Select order.
  • Click Open Project.


Figure-9.11

  • Observe that the order project node appears under Projects tab window.

2. Change the Relative URL to order.xhtml.  (This is the URL that gets accessed when the application starts.)  If you don’t take this step, the application will try to display index.xhtml, which does not exist.


Figure-9.12


Figure-9.13

3. Build and run order project.

  • Right-click order project and select Run.
  • Observe that browser gets displayed.

Figure-9.14


Figure-9.15


Figure-9.16


Figure-9.17


Figure-9.18


Figure-9.19


Figure-9.20

 Trouble-shooting: If you experience the problem below, it is because you have not changed the Relative URL as described above.


Figure-9.21

(9.2) Control flow of “viewing all orders”

1. The order.xhtml is accessed.  The #{orderManager.orders} calls getOrders() method of the OrderManager class.

 


<h:dataTable
var=”order”
value=”#{orderManager.orders}”
rules=”all”
cellpadding=”5″>
<h:column>
<f:facet name=”header”>
<h:outputText value=”Order ID” />
</f:facet>
<h:form>
<h:commandLink id=”order_id_link” action=”lineItem”>
<h:outputText value=”#{order.orderId}” />
<f:setPropertyActionListener target=”#{orderManager.currentOrder}” value=”#{order.orderId}” />
</h:commandLink>
</h:form>
</h:column>
<h:column>
<f:facet name=”header”>
<h:outputText value=”Shipment Info” />
</f:facet>
<h:outputText value=”#{order.shipmentInfo}” />
</h:column>
<h:column>
<f:facet name=”header”>
<h:outputText value=”Status” />
</f:facet>
<h:outputText value=”#{order.status}” />
</h:column>
<h:column>
<f:facet name=”header”>
<h:outputText value=”Last Updated” />
</f:facet>
<h:outputText value=”#{order.lastUpdate}” />
</h:column>
<h:column>
<f:facet name=”header”>
<h:outputText value=”Discount” />
</f:facet>
<h:outputText value=”#{order.discount}%” />
</h:column>
<h:column>
<f:facet name=”header”>
<h:outputText value=”Actions” />
</f:facet>
<h:form>
<h:commandLink value=”Delete” actionListener=”#{orderManager.removeOrder}” action=”order”>
<f:param name=”deleteOrderId” value=”#{order.orderId}” />
</h:commandLink>
</h:form>
</h:column>
</h:dataTable>

order.xhtml

2. The getOrders() method of the OrderManager class calls getOrders() method of the RequestBean class.   Note that the RequestBean is injected.


@ManagedBean
@SessionScoped
public class OrderManager {
private static Logger logger = Logger.getLogger(“order.web.OrderManager”);
private Boolean findVendorTableDisabled = true;
private Boolean partsTableDisabled = true;
private Integer currentOrder;
private Integer newOrderId;
private List<Part> newOrderParts;
private List<Part> newOrderSelectedParts;
private List<Order> orders;
private List<String> vendorSearchResults;
private Long selectedVendorPartNumber;
@EJB
private RequestBean request;
private String newOrderShippingInfo;
private String selectedPartNumber;
private String vendorName;
private char newOrderStatus;
private int newOrderDiscount;
private int selectedPartRevision;

/**
* @return the orders
*/
public List<Order> getOrders() {
try {
this.orders = request.getOrders();
} catch (Exception e) {
e.printStackTrace();
}

return orders;
}

OrderManager.java

3. The getOrders() method of the RequestBean class calls a Named query called “findAllOrders”, which is defined in the Order class.

    …
public List<Order> getOrders() {
try {
return (List<Order>) em.createNamedQuery(“findAllOrders”)
.getResultList();
} catch (Exception e) {
throw new EJBException(e.getMessage());
}
}

RequestBean.java

4. The “findAllOrders” Named query performs JPQL “SELECT o FROM Order o ORDER BY o.orderId”.


@Entity
@Table(name = “PERSISTENCE_ORDER_ORDER”)
@NamedQuery(name = “findAllOrders”, query = “SELECT o FROM Order o ”
+ “ORDER BY o.orderId”)
public class Order implements java.io.Serializable {
private Collection<LineItem> lineItems;
private Date lastUpdate;
private Integer orderId;
private String shipmentInfo;
private char status;
private int discount;

public Order() {
this.lastUpdate = new Date();
this.lineItems = new ArrayList<LineItem>();
}

Order.java

(9.3) Control flow of “creating an order”

1. The submitOrder(..) method of the OrderManager class is invoked when a user submits an order.


<ui:define name=”newOrderForm”>
<h:form>
<h:outputLabel for=”orderIdInputText” rendered=”true” value=”Order ID: ” />
<h:inputText id=”orderIdInputText” required=”true” value=”#{orderManager.newOrderId}” /><br />

<h:outputLabel for=”shipmentInfoInputText” rendered=”true” value=”Shipment Info: ” />
<h:inputText id=”shipmentInfoInputText” required=”true” value=”#{orderManager.newOrderShippingInfo}” /><br />

<h:outputLabel for=”statusMenu” rendered=”true” value=”Status: ” />
<h:selectOneMenu id=”statusMenu” required=”true” value=”#{orderManager.newOrderStatus}”>
<f:selectItem itemValue=”Y” itemLabel=”Complete” />
<f:selectItem itemValue=”N” itemLabel=”Pending” />
</h:selectOneMenu><br />

<h:outputLabel for=”discountMenu” rendered=”true” value=”Discount: ” />
<h:selectOneMenu id=”discountMenu” required=”true” value=”#{orderManager.newOrderDiscount}”>
<f:selectItem itemValue=”0″ itemLabel=”0 %” />
<f:selectItem itemValue=”5″ itemLabel=”5 %” />
<f:selectItem itemValue=”10″ itemLabel=”10 %” />
<f:selectItem itemValue=”15″ itemLabel=”15 %” />
<f:selectItem itemValue=”20″ itemLabel=”20 %” />
<f:selectItem itemValue=”25″ itemLabel=”25 %” />
<f:selectItem itemValue=”30″ itemLabel=”30 %” />
<f:selectItem itemValue=”35″ itemLabel=”35 %” />
<f:selectItem itemValue=”40″ itemLabel=”40 %” />
</h:selectOneMenu><br />

<h:commandButton value=”Submit” action=”#{orderManager.submitOrder}” />
</h:form>

</ui:define>

order.xhtml

2. The submitOrder() method calls createOrder(..) method of the RequestBean class.


@EJB
private RequestBean request;

public void submitOrder() {
try {
request.createOrder(
newOrderId,
newOrderStatus,
newOrderDiscount,
newOrderShippingInfo);

logger.info(
“Created new order with order ID ” + newOrderId
+ “, status ” + newOrderStatus + “, discount ”
+ newOrderDiscount + “, and shipping info ”
+ newOrderShippingInfo + “.”);
this.newOrderId = null;
this.newOrderDiscount = 0;
this.newOrderParts = null;
this.newOrderShippingInfo = null;
} catch (Exception e) {
logger.warning(“Problem creating order in submitOrder.”);
}
}

OrderManager.java

3. The createOrder(..) method of the RequestBean creates an order and persists it.


public void createOrder(
Integer orderId,
char status,
int discount,
String shipmentInfo) {
try {
Order order = new Order(orderId, status, discount, shipmentInfo);
em.persist(order);
} catch (Exception e) {
throw new EJBException(e.getMessage());
}
}

RequestBean.java

Summary

In this exercise,  you have explored with the “order” sample application that comes with Java EE 6 tutorial.

Exercise 10: Build and run “roster” sample application (from “Java EE 6 tutorial”)

 

In this exercise, you are going to build and run “roster” sample application from Java EE 6 tutorial.  For detailed description of this example, please see “The roster Application” section of the tutorial.

(10.1) Open, build, and run “roster” sample application (from “Java EE 6 tutorial”)

1. Open roster NetBeans project.

  • Select File->Open Project (Ctrl+Shift+O).
  • Observe that the Open Project dialog box appears.
  • Browse down to <GlassFish-v3-Installation-Directory>/glassfish/docs/javaee-tutorial/examples/persistence directory.  (This is “Java EE 6 tutorial” examples.)
  • Select roster.
  • Check Open Required Projects
  • Click Open Project.

2. Open required projects.

  • Observe that the roster-app-client and roster-ejb projects are opened.

3. Build and run roster project.

  • Right-click roster project and select Run.
  • Observe the result in the Output window.

Figure-10.11

(10.2)  Study “roster-app-client” project

1. RosterClient.java


Figure-10.21

/*
* Copyright 2009 Sun Microsystems, Inc.
* All rights reserved.  You may not modify, use,
* reproduce, or distribute this software except in
* compliance with  the terms of the License at:
* http://developer.sun.com/berkeley_license.html
*/

package roster.client;

import java.util.Iterator;
import java.util.List;
import javax.ejb.EJB;
import roster.request.Request;
import roster.util.LeagueDetails;
import roster.util.PlayerDetails;
import roster.util.TeamDetails;

public class RosterClient {
@EJB
private static Request request;

public RosterClient(String[] args) {
}

public static void main(String[] args) {
RosterClient client = new RosterClient(args);

try {
client.insertInfo();
client.getSomeInfo();
client.getMoreInfo();
client.removeInfo();

System.exit(0);
} catch (Exception ex) {
System.err.println(“Caught an exception:”);
ex.printStackTrace();
}
}

private void insertInfo() {
try {
// Leagues
request.createLeague(new LeagueDetails(“L1”, “Mountain”, “Soccer”));
request.createLeague(
new LeagueDetails(“L2”, “Valley”, “Basketball”));
request.createLeague(
new LeagueDetails(“L3”, “Foothills”, “Soccer”));
request.createLeague(
new LeagueDetails(“L4”, “Alpine”, “Snowboarding”));

// Teams
request.createTeamInLeague(
new TeamDetails(“T1”, “Honey Bees”, “Visalia”),
“L1”);
request.createTeamInLeague(
new TeamDetails(“T2”, “Gophers”, “Manteca”),
“L1”);
request.createTeamInLeague(
new TeamDetails(“T5”, “Crows”, “Orland”),
“L1”);

request.createTeamInLeague(
new TeamDetails(“T3”, “Deer”, “Bodie”),
“L2”);
request.createTeamInLeague(
new TeamDetails(“T4”, “Trout”, “Truckee”),
“L2”);

request.createTeamInLeague(
new TeamDetails(“T6”, “Marmots”, “Auburn”),
“L3”);
request.createTeamInLeague(
new TeamDetails(“T7”, “Bobcats”, “Grass Valley”),
“L3”);
request.createTeamInLeague(
new TeamDetails(“T8”, “Beavers”, “Placerville”),
“L3”);

request.createTeamInLeague(
new TeamDetails(“T9”, “Penguins”, “Incline Village”),
“L4”);
request.createTeamInLeague(
new TeamDetails(“T10”, “Land Otters”, “Tahoe City”),
“L4”);

// Players, Team T1
request.createPlayer(“P1”, “Phil Jones”, “goalkeeper”, 100.00);
request.addPlayer(“P1”, “T1”);

request.createPlayer(“P2”, “Alice Smith”, “defender”, 505.00);
request.addPlayer(“P2”, “T1”);

request.createPlayer(“P3”, “Bob Roberts”, “midfielder”, 65.00);
request.addPlayer(“P3”, “T1”);

request.createPlayer(“P4”, “Grace Phillips”, “forward”, 100.00);
request.addPlayer(“P4”, “T1”);

request.createPlayer(“P5”, “Barney Bold”, “defender”, 100.00);
request.addPlayer(“P5”, “T1”);

// Players, Team T2
request.createPlayer(“P6”, “Ian Carlyle”, “goalkeeper”, 555.00);
request.addPlayer(“P6”, “T2”);

request.createPlayer(
“P7”,
“Rebecca Struthers”,
“midfielder”,
777.00);
request.addPlayer(“P7”, “T2”);

request.createPlayer(“P8”, “Anne Anderson”, “forward”, 65.00);
request.addPlayer(“P8”, “T2”);

request.createPlayer(“P9”, “Jan Wesley”, “defender”, 100.00);
request.addPlayer(“P9”, “T2”);

request.createPlayer(“P10”, “Terry Smithson”, “midfielder”, 100.00);
request.addPlayer(“P10”, “T2”);

// Players, Team T3
request.createPlayer(“P11”, “Ben Shore”, “point guard”, 188.00);
request.addPlayer(“P11”, “T3”);

request.createPlayer(
“P12”,
“Chris Farley”,
“shooting guard”,
577.00);
request.addPlayer(“P12”, “T3”);

request.createPlayer(
“P13”,
“Audrey Brown”,
“small forward”,
995.00);
request.addPlayer(“P13”, “T3”);

request.createPlayer(
“P14”,
“Jack Patterson”,
“power forward”,
100.00);
request.addPlayer(“P14”, “T3”);

request.createPlayer(“P15”, “Candace Lewis”, “point guard”, 100.00);
request.addPlayer(“P15”, “T3”);

// Players, Team T4
request.createPlayer(
“P16”,
“Linda Berringer”,
“point guard”,
844.00);
request.addPlayer(“P16”, “T4”);

request.createPlayer(
“P17”,
“Bertrand Morris”,
“shooting guard”,
452.00);
request.addPlayer(“P17”, “T4”);

request.createPlayer(“P18”, “Nancy White”, “small forward”, 833.00);
request.addPlayer(“P18”, “T4”);

request.createPlayer(“P19”, “Billy Black”, “power forward”, 444.00);
request.addPlayer(“P19”, “T4”);

request.createPlayer(“P20”, “Jodie James”, “point guard”, 100.00);
request.addPlayer(“P20”, “T4”);

// Players, Team T5
request.createPlayer(“P21”, “Henry Shute”, “goalkeeper”, 205.00);
request.addPlayer(“P21”, “T5”);

request.createPlayer(“P22”, “Janice Walker”, “defender”, 857.00);
request.addPlayer(“P22”, “T5”);

request.createPlayer(
“P23”,
“Wally Hendricks”,
“midfielder”,
748.00);
request.addPlayer(“P23”, “T5”);

request.createPlayer(“P24”, “Gloria Garber”, “forward”, 777.00);
request.addPlayer(“P24”, “T5”);

request.createPlayer(“P25”, “Frank Fletcher”, “defender”, 399.00);
request.addPlayer(“P25”, “T5”);

// Players, Team T9
request.createPlayer(“P30”, “Lakshme Singh”, “downhill”, 450.00);
request.addPlayer(“P30”, “T9”);

request.createPlayer(“P31”, “Mariela Prieto”, “freestyle”, 420.00);
request.addPlayer(“P31”, “T9”);

// Players, Team T10
request.createPlayer(“P32”, “Soren Johannsen”, “freestyle”, 375.00);
request.addPlayer(“P32”, “T10”);

request.createPlayer(“P33”, “Andre Gerson”, “freestyle”, 396.00);
request.addPlayer(“P33”, “T10”);

request.createPlayer(“P34”, “Zoria Lepsius”, “downhill”, 431.00);
request.addPlayer(“P34”, “T10”);

// Players, no team
request.createPlayer(“P26”, “Hobie Jackson”, “pitcher”, 582.00);
request.createPlayer(“P27”, “Melinda Kendall”, “catcher”, 677.00);

// Players, multiple teams
request.createPlayer(
“P28”,
“Constance Adams”,
“substitute”,
966.00);
request.addPlayer(“P28”, “T1”);
request.addPlayer(“P28”, “T3”);

// Adding existing players to second soccer league
request.addPlayer(“P24”, “T6”);
request.addPlayer(“P21”, “T6”);
request.addPlayer(“P9”, “T6”);
request.addPlayer(“P7”, “T5”);
} catch (Exception ex) {
System.err.println(“Caught an exception:”);
ex.printStackTrace();
}
}

private void getSomeInfo() {
try {
List<PlayerDetails> playerList;
List<TeamDetails> teamList;
List<LeagueDetails> leagueList;

System.out.println(“List all players in team T2:”);
playerList = request.getPlayersOfTeam(“T2”);
printDetailsList(playerList);
System.out.println();

System.out.println(“List all teams in league L1:”);
teamList = request.getTeamsOfLeague(“L1”);
printDetailsList(teamList);
System.out.println();

System.out.println(“List all defenders:”);
playerList = request.getPlayersByPosition(“defender”);
printDetailsList(playerList);
System.out.println();

System.out.println(“List the leagues of player P28”);
leagueList = request.getLeaguesOfPlayer(“P28”);
printDetailsList(leagueList);
System.out.println();
} catch (Exception ex) {
System.err.println(“Caught an exception:”);
ex.printStackTrace();
}
} // getSomeInfo

private void getMoreInfo() {
try {
LeagueDetails leagueDetails;
TeamDetails teamDetails;
PlayerDetails playerDetails;
List<PlayerDetails> playerList;
List<TeamDetails> teamList;
List<LeagueDetails> leagueList;
List<String> sportList;

System.out.println(“Details of league L1:”);
leagueDetails = request.getLeague(“L1”);
System.out.println(leagueDetails.toString());
System.out.println();

System.out.println(“Details of team T3:”);
teamDetails = request.getTeam(“T3”);
System.out.println(teamDetails.toString());
System.out.println();

System.out.println(“Details of player P20:”);
playerDetails = request.getPlayer(“P20”);
System.out.println(playerDetails.toString());
System.out.println();

System.out.println(“List all teams in league L3:”);
teamList = request.getTeamsOfLeague(“L3”);
printDetailsList(teamList);
System.out.println();

System.out.println(“List all players:”);
playerList = request.getAllPlayers();
printDetailsList(playerList);
System.out.println();

System.out.println(“List all players not on a team:”);
playerList = request.getPlayersNotOnTeam();
printDetailsList(playerList);
System.out.println();

System.out.println(“Details of Jack Patterson, a power forward:”);
playerList = request.getPlayersByPositionAndName(
“power forward”,
“Jack Patterson”);
printDetailsList(playerList);
System.out.println();

System.out.println(“List all players in the city of Truckee:”);
playerList = request.getPlayersByCity(“Truckee”);
printDetailsList(playerList);
System.out.println();

System.out.println(“List all soccer players:”);
playerList = request.getPlayersBySport(“Soccer”);
printDetailsList(playerList);
System.out.println();

System.out.println(“List all players in league L1:”);
playerList = request.getPlayersByLeagueId(“L1”);
printDetailsList(playerList);
System.out.println();

System.out.println(
“List all players making a higher salary than Ian Carlyle:”);
playerList = request.getPlayersByHigherSalary(“Ian Carlyle”);
printDetailsList(playerList);
System.out.println();

System.out.println(
“List all players with a salary between 500 and 800:”);
playerList = request.getPlayersBySalaryRange(500.00, 800.00);
printDetailsList(playerList);
System.out.println();

System.out.println(“List all players of team T5:”);
playerList = request.getPlayersOfTeam(“T5”);
printDetailsList(playerList);
System.out.println();

System.out.println(“List all the leagues of player P28:”);
leagueList = request.getLeaguesOfPlayer(“P28”);
printDetailsList(leagueList);
System.out.println();

System.out.println(“List all the sports of player P28:”);
sportList = request.getSportsOfPlayer(“P28”);
printDetailsList(sportList);
System.out.println();
} catch (Exception ex) {
System.err.println(“Caught an exception:”);
ex.printStackTrace();
}
} // getMoreInfo

private void removeInfo() {
try {
System.out.println(“Removing team T6.”);
request.removeTeam(“T6”);
System.out.println();

System.out.println(“Removing player P24”);
request.removePlayer(“P24”);
System.out.println();
} catch (Exception ex) {
System.err.println(“Caught an exception:”);
ex.printStackTrace();
}
}

private static void printDetailsList(List list) {
Iterator i = list.iterator();

while (i.hasNext()) {
Object details = (Object) i.next();

System.out.println(details.toString());
}

System.out.println();
} // printDetailsList
}

RosterClient.java

2. See the properties of the roster-app-client project.

  • Right click the roster-app-client project and select Properties.
  • Click Libraries on the left and observe that roster-ejb.jar is in its class path.


Figure-10.22

  • Click Run on the left and observe that the roster.client.RosterClient is the Main class meaning main() method of the class gets executed when the project is run.


Figure-10.23

 

(10.3)  Study “roster-ejb” project

1. Request.java.

/*
* Copyright 2009 Sun Microsystems, Inc.
* All rights reserved.  You may not modify, use,
* reproduce, or distribute this software except in
* compliance with  the terms of the License at:
* http://developer.sun.com/berkeley_license.html
*/

package roster.request;

import java.util.List;
import javax.ejb.Remote;
import roster.util.LeagueDetails;
import roster.util.PlayerDetails;
import roster.util.TeamDetails;

@Remote
public interface Request {
void addPlayer(
String playerId,
String teamId);

void createLeague(LeagueDetails leagueDetails);

void createPlayer(
String id,
String name,
String position,
double salary);

void createTeamInLeague(
TeamDetails teamDetails,
String leagueId);

void dropPlayer(
String playerId,
String teamId);

List<PlayerDetails> getAllPlayers();

LeagueDetails getLeague(String leagueId);

List<LeagueDetails> getLeaguesOfPlayer(String playerId);

PlayerDetails getPlayer(String playerId);

List<PlayerDetails> getPlayersByCity(String city);

List<PlayerDetails> getPlayersByHigherSalary(String name);

List<PlayerDetails> getPlayersByLeagueId(String leagueId);

List<PlayerDetails> getPlayersByPosition(String position);

List<PlayerDetails> getPlayersByPositionAndName(
String position,
String name);

List<PlayerDetails> getPlayersBySalaryRange(
double low,
double high);

List<PlayerDetails> getPlayersBySport(String sport);

List<PlayerDetails> getPlayersNotOnTeam();

List<PlayerDetails> getPlayersOfTeam(String teamId);

List<String> getSportsOfPlayer(String playerId);

TeamDetails getTeam(String teamId);

List<TeamDetails> getTeamsOfLeague(String leagueId);

void removeLeague(String leagueId);

void removePlayer(String playerId);

void removeTeam(String teamId);
}

Request.java

2. RequestBean.java.

/*
* Copyright 2009 Sun Microsystems, Inc.
* All rights reserved.  You may not modify, use,
* reproduce, or distribute this software except in
* compliance with  the terms of the License at:
* http://developer.sun.com/berkeley_license.html
*/

package roster.request;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJBException;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import roster.entity.League;
import roster.entity.League_;
import roster.entity.Player;
import roster.entity.Player_;
import roster.entity.SummerLeague;
import roster.entity.Team;
import roster.entity.Team_;
import roster.entity.WinterLeague;
import roster.util.IncorrectSportException;
import roster.util.LeagueDetails;
import roster.util.PlayerDetails;
import roster.util.TeamDetails;

/**
* This is the bean class for the RequestBean enterprise bean.
* @author ian
*/
@Stateful
public class RequestBean implements Request {
private static final Logger logger = Logger.getLogger(
“roster.request.RequestBean”);
private CriteriaBuilder cb;
@PersistenceContext
private EntityManager em;

@PostConstruct
private void init() {
cb = em.getCriteriaBuilder();
}

public void createPlayer(
String id,
String name,
String position,
double salary) {
logger.info(“createPlayer”);

try {
Player player = new Player(id, name, position, salary);
em.persist(player);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public void addPlayer(
String playerId,
String teamId) {
logger.info(“addPlayer”);

try {
Player player = em.find(Player.class, playerId);
Team team = em.find(Team.class, teamId);

team.addPlayer(player);
player.addTeam(team);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public void removePlayer(String playerId) {
logger.info(“removePlayer”);

try {
Player player = em.find(Player.class, playerId);

Collection<Team> teams = player.getTeams();
Iterator<Team> i = teams.iterator();

while (i.hasNext()) {
Team team = i.next();
team.dropPlayer(player);
}

em.remove(player);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<PlayerDetails> getPlayersByPosition(String position) {
logger.info(“getPlayersByPosition”);

List<Player> players = null;

try {
CriteriaQuery<Player> cq = cb.createQuery(Player.class);

if (cq != null) {
Root<Player> player = cq.from(Player.class);

// Get MetaModel from Root
//EntityType<Player> Player_ = player.getModel();

// set the where clause
cq.where(
cb.equal(
player.get(Player_.position),
position));
cq.select(player);

TypedQuery<Player> q = em.createQuery(cq);
players = q.getResultList();
}

return copyPlayersToDetails(players);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<PlayerDetails> getPlayersByHigherSalary(String name) {
logger.info(“getPlayersByHigherSalary”);

List<Player> players = null;

try {
CriteriaQuery<Player> cq = cb.createQuery(Player.class);

if (cq != null) {
Root<Player> player1 = cq.from(Player.class);
Root<Player> player2 = cq.from(Player.class);

// Get MetaModel from Root
//EntityType<Player> Player_ = player1.getModel();

// create a Predicate object that finds players with a salary
// greater than player1
Predicate gtPredicate = cb.greaterThan(
player1.get(Player_.salary),
player2.get(Player_.salary));

// create a Predicate object that finds the player based on
// the name parameter
Predicate equalPredicate = cb.equal(
player1.get(Player_.name),
name);
// set the where clause with the predicates
cq.where(gtPredicate, equalPredicate);
// set the select clause, and return only unique entries
cq.select(player1)
.distinct(true);

TypedQuery<Player> q = em.createQuery(cq);
players = q.getResultList();
}

return copyPlayersToDetails(players);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<PlayerDetails> getPlayersBySalaryRange(
double low,
double high) {
logger.info(“getPlayersBySalaryRange”);

List<Player> players = null;

try {
CriteriaQuery<Player> cq = cb.createQuery(Player.class);

if (cq != null) {
Root<Player> player = cq.from(Player.class);

// Get MetaModel from Root
//EntityType<Player> Player_ = player.getModel();

// set the where clause
cq.where(
cb.between(
player.get(Player_.salary),
low,
high));
// set the select clause
cq.select(player)
.distinct(true);

TypedQuery<Player> q = em.createQuery(cq);
players = q.getResultList();
}

return copyPlayersToDetails(players);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<PlayerDetails> getPlayersByLeagueId(String leagueId) {
logger.info(“getPlayersByLeagueId”);

List<Player> players = null;

try {
CriteriaQuery<Player> cq = cb.createQuery(Player.class);

if (cq != null) {
Root<Player> player = cq.from(Player.class);
Join<Player, Team> team = player.join(Player_.teams);
Join<Team, League> league = team.join(Team_.league);

// Get MetaModel from Root
//EntityType<Player> Player_ = player.getModel();

// set the where clause
cq.where(
cb.equal(
league.get(League_.id),
leagueId));
cq.select(player)
.distinct(true);

TypedQuery<Player> q = em.createQuery(cq);
players = q.getResultList();
}

return copyPlayersToDetails(players);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<PlayerDetails> getPlayersBySport(String sport) {
logger.info(“getPlayersByLeagueId”);

List<Player> players = null;

try {
CriteriaQuery<Player> cq = cb.createQuery(Player.class);

if (cq != null) {
Root<Player> player = cq.from(Player.class);
Join<Player, Team> team = player.join(Player_.teams);
Join<Team, League> league = team.join(Team_.league);

// Get MetaModel from Root
//EntityType<Player> Player_ = player.getModel();

// set the where clause
cq.where(
cb.equal(
league.get(League_.sport),
sport));
cq.select(player)
.distinct(true);

TypedQuery<Player> q = em.createQuery(cq);
players = q.getResultList();
}

return copyPlayersToDetails(players);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<PlayerDetails> getPlayersByCity(String city) {
logger.info(“getPlayersByCity”);

List<Player> players = null;

try {
CriteriaQuery<Player> cq = cb.createQuery(Player.class);

if (cq != null) {
Root<Player> player = cq.from(Player.class);
Join<Player, Team> team = player.join(Player_.teams);

// Get MetaModel from Root
//EntityType<Player> Player_ = player.getModel();

// set the where clause
cq.where(
cb.equal(
team.get(Team_.city),
city));
cq.select(player)
.distinct(true);

TypedQuery<Player> q = em.createQuery(cq);
players = q.getResultList();
}

return copyPlayersToDetails(players);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<PlayerDetails> getAllPlayers() {
logger.info(“getAllPlayers”);

List<Player> players = null;

try {
CriteriaQuery<Player> cq = cb.createQuery(Player.class);

if (cq != null) {
Root<Player> player = cq.from(Player.class);

cq.select(player);

TypedQuery<Player> q = em.createQuery(cq);
players = q.getResultList();
}

return copyPlayersToDetails(players);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<PlayerDetails> getPlayersNotOnTeam() {
logger.info(“getPlayersNotOnTeam”);

List<Player> players = null;

try {
CriteriaQuery<Player> cq = cb.createQuery(Player.class);

if (cq != null) {
Root<Player> player = cq.from(Player.class);

// Get MetaModel from Root
//EntityType<Player> Player_ = player.getModel();

// set the where clause
cq.where(cb.isEmpty(player.get(Player_.teams)));
cq.select(player)
.distinct(true);

TypedQuery<Player> q = em.createQuery(cq);
players = q.getResultList();
}

return copyPlayersToDetails(players);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<PlayerDetails> getPlayersByPositionAndName(
String position,
String name) {
logger.info(“getPlayersByPositionAndName”);

List<Player> players = null;

try {
CriteriaQuery<Player> cq = cb.createQuery(Player.class);

if (cq != null) {
Root<Player> player = cq.from(Player.class);

// Get MetaModel from Root
//EntityType<Player> Player_ = player.getModel();

// set the where clause
cq.where(
cb.equal(
player.get(Player_.position),
position),
cb.equal(
player.get(Player_.name),
name));
cq.select(player)
.distinct(true);

TypedQuery<Player> q = em.createQuery(cq);
players = q.getResultList();
}

return copyPlayersToDetails(players);
} catch (Exception ex) {
throw new EJBException(ex);
}
}

public List<LeagueDetails> getLeaguesOfPlayer(String playerId) {
logger.info(“getLeaguesOfPlayer”);

List<LeagueDetails> detailsList = new ArrayList<LeagueDetails>();
List<League> leagues = null;

try {
CriteriaQuery<League> cq = cb.createQuery(League.class);

if (cq != null) {
Root<League> league = cq.from(League.class);

//EntityType<League> League_ = league.getModel();
Join<League, Team> team = league.join(League_.teams);

//EntityType<Team> Team_ = team.getModel();
Join<Team, Player> player = team.join(Team_.players);

cq.where(
cb.equal(
player.get(Player_.id),
playerId));
cq.select(league)
.distinct(true);

TypedQuery<League> q = em.createQuery(cq);
leagues = q.getResultList();
}
} catch (Exception ex) {
throw new EJBException(ex);
}

Iterator<League> i = leagues.iterator();

while (i.hasNext()) {
League league = (League) i.next();
LeagueDetails leagueDetails = new LeagueDetails(
league.getId(),
league.getName(),
league.getSport());
detailsList.add(leagueDetails);
}

return detailsList;
}

public List<String> getSportsOfPlayer(String playerId) {
logger.info(“getSportsOfPlayer”);

List<String> sports = new ArrayList<String>();

try {
CriteriaQuery<String> cq = cb.createQuery(String.class);

if (cq != null) {
Root<Player> player = cq.from(Player.class);
Join<Player, Team> team = player.join(Player_.teams);
Join<Team, League> league = team.join(Team_.league);

// Get MetaModel from Root
//EntityType<Player> Player_ = player.getModel();

// set the where clause
cq.where(
cb.equal(
player.get(Player_.id),
playerId));
cq.select(league.get(League_.sport))
.distinct(true);

TypedQuery<String> q = em.createQuery(cq);
sports = q.getResultList();
}

//        Player player = em.find(Player.class, playerId);
//        Iterator<Team> i = player.getTeams().iterator();
//        while (i.hasNext()) {
//            Team team = i.next();
//            League league = team.getLeague();
//            sports.add(league.getSport());
//        }
} catch (Exception ex) {
throw new EJBException(ex);
}

return sports;
}


}

2. Generated Metamodel classes

 

Summary

In this exercise,  you have explored the “roster” sample application that comes with Java EE 6 tutorial.

 

Homework Exercise

 

The homework is revised since the original homework indeed has a flaw.  The code snippets are shown as hints.  The structure of the homework project is quite similar to the jpa2.0_mapping_collection_embeddables_relation project.

 

1. The homework is to build a standalone JPA application called my_jpa2.0 project as following.

  • Exercise point: Mapping with @ElementCollection
    • School entity class have schoolname field, which is String type, and district field, which is District class.  See a snippet of the School class below.

@Entity
public class School implements Serializable {

@Id
@GeneratedValue
@Column(name = “SCHOOL_ID”)
private int id;
private String schoolname;

private District district;

    • The District class is Embeddable type and has a set of Student’s.  It also has districtname field, which is String type. See a snippet of District class below.

@Embeddable
public class District implements Serializable{

private String districtname;

@OneToMany(cascade=CascadeType.ALL, mappedBy=”school”)
private Set<Student> students;

    • The Student class is an entity class and  has studentname field, which is String type, and grade field, which is double type.  See a snippet of Student class below.

@Entity
@Table(name = “STUDENT_TABLE”)
public class Student implements Serializable {

@Id
@Column(name = “STUDENT_ID”)
@GeneratedValue
private int id;
private String studentname;
private double grade;

// Bi-directional one-to-many relationship
@ManyToOne(optional = true)
private School school;

    • In the Main.java, as samples, add at least 3 schools.  Each district of corresponding school has at least 2 students.
  • Exercise point: Criteria  API
    • In the Main.java, perform both JPQL and Criteria API as following.  Metamodel class does not have to be used.
      • Get all schools who have students whose grade is 3.0 or above
2. Send the following files to javaee6-homeworks@sun.com with Subject as homework_javaee6_jpa2.0.
  • Zip file of the the my_jpa2.0 NetBeans project.  (Someone else should be able to open and run it as a NetBeans project.)  You can use your favorite zip utility or you can use “jar” utility that comes with JDK as following.
    • cd <parent directory that contains my_jpa2.0 directory> (assuming you named your project as my_jpa2.0)
    • jar cvf my_jpa2.0.zip my_jpa2.0 (my_jpa2.0 should contain nbproject directory)
Please reduce the size of the zip file by right clicking the project and then selecting Clean before zipping the file.
  • Captured output screen  – name it as homework_javaee6_jpa2.0.gif or homework_javaee6_jpa2.0.jpg (or homework_javaee6_jpa2.0.<whatever graphics format>)
    • Any screen capture that shows that your program is working is good enough.

 

 

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.