Persisting Entity Classes using XML in JPA

Preface

This document explains the working of a JPA application purely based on XML configurations. This explains how to create entity classes without using any annotations in Java classes. Entire configuration is done using xml files.

Introduction

Persistence is one of the major challenges for enterprise applications. JPA is the persistence standard from Sun Microsystems. JPA supports two ways of configuring persistence information- through annotations and XML files. This article discusses the XML based approach towards embedding persistence information for the entity classes.

Setting up the environment

JPA is light-weight persistence model.  It works for both JavaSE and JavaEE applications. All the required class files are present in the JavaEE.jar file which should be added to the classpath. Along with the JavaEE.jar file, we need to add the Persistence Provider jar file as well to the classpath. The provider can be Toplink/ Hibernate/ App server specific persistence provider. In this application, we’ve used Toplink as the persistence provider. So we need to add toplink-essentials.jar file as well in the class path.

To summarize, the jar files required are:
1.JavaEE.jar
2.ToplinkEssentials.jar (Replace with the jar file for Persistence Provider, in case you want to use other persistence provider)
3.derbyClient.jar (For JavaDB (Derby) Database, replace this with the jar file of your database)

Instead of adding the configuration details in the entity class in the form of annotations, we’ll add the configuration information in the orm.xml file. Before we look into the code, let us discuss the orm.xml file in detail.

orm.xml

orm.xml file contains all the configuration details required for mapping a class to a relational database table. These details include the primary key of the entity class and the various constraints/ rules to be applied for the primary key. Other details about the entity class include the various attributes of the entity class and columns to which the attributes should be mapped. We can also specify multiple constraints for the same attribute. Other configurable things include information about the various relationships the entity may have with other entities (one-to-one, many-to-one, many-to-many or one-to-many), embedded attributes, information about the version and transient attributes.

One application can have multiple entities. The configuration details about all these entity classes, embeddable classes go inside the same orm.xml file. Name of this configuration file can be anything, not mandatorily orm.xml. It should be placed in META-INF subdirectory along with the persistence.xml file. Persistence.xml file should include the orm.xml file. Please find below sample orm.xml and persistence.xml file. The xml schema definitions are highlighted for both. Also, please note the entry required in persistence.xml for including the orm.xml file.

PFB the entries made in a sample orm.xml, which’ll persist employee instances to the database.

<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm    
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
    version="1.0">
    <description>My First JPA XML Application</description>
    <package>entity</package> 
    <entity class="entity.Employee" name="Employee">        
        <table name="EMPLOYEETABLE"/>
        <attributes>
            <id name="empId">
                <generated-value strategy="TABLE"/>
            </id>
            <basic name="empName">
                <column name="EMP_NAME" length="100"/>
            </basic>
            <basic name="empSalary">
            </basic>
        </attributes>
   </entity>
</entity-mappings>

Different properties in orm.xml file

The various properties in the orm.xml in the order defined in xml schema definition are discussed below:

  1. Root tag is <entity-mappings>
        It contains the following four types of elements:
    1. The persistence-unit-metadata element contains metadata for the entire persistence unit. It is undefined if this element occurs in multiple mapping files within the same persistence unit.
    2. The package, schema, catalog and access elements apply to all the entity, mapped-superclass and embeddable elements defined in the same file in which they occur.
    3. The sequence-generator, table-generator, named-query, named-native-query and sql-result-set-mapping elements are global to the persistence unit.
    4. The entity, mapped-superclass and embeddable elements each define the mapping information for a managed persistent class. The mapping information contained in these elements may be complete or it may be partial.
  2. <description>One line string information about the entity classes in the application.
  3. <package>specifies the package of the classes listed within the sub elements and attributes of the same mapping file only.
  4. <entity class= “entity.Employee” name= “Employee”>
    1. classAttribute defines the fully qualified class name of the entity class
    2. name: Attribute defines the name of the entity
    3. entity: tag can be repeated to embed mapping information for all the entity classes in the application.
    The Sub-Tags of entity tag are
    <table>
    maps the database table to which the entity class shall be persisted
    <id-class>
    overrides or creates a new id-class setting
    <inheritance>
    overrides or creates a new inheritance setting
    <discriminator-value>
    overrides or creates a new discriminator value setting, useful in Single_Table Inheritance strategy.
    <discriminator-column>
    overrides or creates a new discriminator column setting, used while configuring Super class in Single_Table inheritance strategy.
    <sequence-generator>
    A sequence-generator is unique by name
    <table-generator>
    A table-generator is unique by name
    <named-query>
    used to define named-query for the entity class. Can be repeated to define multiple named queries for the entity class.
    <named-native-query>
    used to define native named query for the entity class.
    <pre-persist>
    creates or overrides a pre-persist setting i.e. the entity listener method to be invoked before persisting the entity instance.
    <post-persist>
    creates or overrides a post-persist setting i.e. the entity listener method to be invoked after persisting the entity instance.
    <pre-remove>
    creates or overrides a pre-remove setting i.e. the entity listener method to be invoked before removing the entity instance.
    <post-remove>
    creates or overrides a post-remove setting i.e. the entity listener method to be invoked after removing the entity instance.
    <pre-update>
    creates or overrides a pre-update setting i.e. the entity listener method to be invoked before updating the entity instance.
    <post-update>
    creates or overrides a post-update setting i.e. the entity listener method to be invoked before updating the entity instance.
    <post-load>
    creates or overrides a post-load setting i.e. the entity listener method to be invoked after loading the entity instance state from database
    <attributes>
    defines the attributes of the entity class which shall be persisted in the database table. The sub tags of the attributes are:
    1. <id>:- this tag defines the id column of the entity class. Cannot be repeated for an entity. An entity class can have only one Id attribute.
      1. <generated-value> :-this is used to define the ID generation strategy to be used for the primary key column.
    2. <basic>:-this tag is used to map the entity columns to the columns in the database table. Should be repeated to provide configurations for all the attributes of the entity class.
      1. <column>:- This tag is used to add the various column-level constraints on the entity attributes. E.g. unique, insertable, updatable, length, precision etc.
    3. <version>:- maps the Version attribute of the entity class.
     

    Development Environment

    We’ve used NetBeans IDE 6.5.1 for creating this JavaSE application for persistence through XML files. NetBeans has persistence support for JPA as well as Hibernate. So, we can choose either Hibernate or Toplink Essentials as the Persistence Provider. Let’s name the application as “JPAEntity”. The name of the entity class is “Employee” and is placed in the package “entity”. “EmpClient.java” is the client class. The xml configuration files are put in META-INF sub directory. The directory structure of the application is as follows:-
    1. First JPA
      • META-INF
        • orm.xml
        • persistence.xml
      • entity
        • Employee.java
        • EmpClient.java
     

    Developing the Application


    • Step1:Start the NetBeans IDE. Create a new Java Application


    • Step 2:Add the jar files for the Persistence Provider (Toplink Essentials in our case), JavaEE.jar and the database driver(DerbyClient.jar in our case) to the classpath.


    • Step 3: Add the entity class “Employee.java” and client class “EmpClient.java” in the package "jpaentity"
      • This is the code of Employee.java
        package jpaentity;
        public class Employee {    
            private int empId;
            private String empName;
            private double empSalary;
            public Employee() {
            }
            public Employee(int empId, String empName, double empSalary) {
                this.empId = empId;
                this.empName = empName;
                this.empSalary = empSalary;
            }
            public int getEmpId() {
                return empId;
            }
            public void setEmpId(int empId) {
                this.empId = empId;
            }
            public String getEmpName() {
                return empName;
            }
            public void setEmpName(String empName) {
                this.empName = empName;
            }
            public double getEmpSalary() {
                return empSalary;
            }
            public void setEmpSalary(double empSalary) {
                this.empSalary = empSalary;
            }
            @Override
            public String toString() {
                return "Employee Id:="+empId+
        +" Employee Name:="+empName+" Employee Salary:="+empSalary;
            }
        }//End of Employee.java


      • This is the code of EmpClient.java
        package jpaentity;
        import java.util.List;
        import javax.persistence.EntityManager;
        import javax.persistence.EntityManagerFactory;
        import javax.persistence.Persistence;
        public class EmpClient {
           private EntityManager em;
           private EntityManagerFactory emf;
           public void initEmfAndEm()
           {
               emf=Persistence.createEntityManagerFactory("JPAEntityPU");
               em=emf.createEntityManager();
           }
           public void cleanup()
           {
                em.close();
           }
           public void insertAndRetrieve()
           {
              System.out.println("-------------------Creating the Objects---------------------");
              Employee empObj1=new Employee(1, "Anu", 1000.0);
              Employee empObj2=new Employee(2, "Rahul", 1500.0);
              System.out.println("-------------------Starting the transaction---------------------");
              em.getTransaction().begin();
              em.persist(empObj1);
              em.persist(empObj2);
              System.out.println("-------------------Committing the transaction---------------------");
              em.getTransaction().commit();
              System.out.println("-------------------Objects saved successfully--------------------");
              System.out.println("*******************************************************************");
              System.out.println("------------------- Reading Objects--------------------");
              List emps=em.createQuery("select p from Employee p").getResultList();
              for (Employee current:emps)
                  System.out.println(current);
              System.out.println("-------------------Finished Reading Objects--------------------");
           }
           public static void main(String args[])
           {
               EmpClient myClient=new EmpClient();
               System.out.println("-------------------Starting the Client---------------------");
               myClient.initEmfAndEm();
               myClient.insertAndRetrieve();
               myClient.cleanup();
               System.out.println("---------------Shutting down the Client---------------------");
           }
        }//End of EmpClient.java

    • Step 4: Set up the database connection. Go to Services Tab in the NetBeans IDE and expand the Databases node. Right click on JavaDB node and select Create Database. Give the database name, username and password and click on OK. The database is created and ready to accept connections.


    • Step 5: Add the persistence unit to the application. Also, add the orm.xml file. The name of the orm.xml file can be changed. We have named it mapping.xml.
      • Following is the code of mapping.xml file
        <?xml version="1.0" encoding="UTF-8" ?>
        <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
            version="1.0">
            <description>My First JPA XML Application</description>
            <package>entity</package>
            <entity class="jpaentity.Employee" name="Employee">
                <table name="EMPLOYEETABLE"/>
                <attributes>
                    <id name="empId">
                        <generated-value strategy="TABLE"/>
                    </id>
                    <basic name="empName">
                        <column name="EMP_NAME" length="100"/>
                    </basic>
                    <basic name="empSalary">
                    </basic>
                </attributes>
           </entity>
        </entity-mappings>


      • Add the following code to the persistence.xml file
        <?xml version="1.0" encoding="UTF-8"?>
        <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
          <persistence-unit name="FirstJPAPU" transaction-type="RESOURCE_LOCAL">
             <provider>oracle.toplink.essentials.PersistenceProvider</provider>
            <mapping-file>\META-INF\orm.xml</mapping-file>   
            <class>jpaentity.Employee</class>
            <properties>
              <property name="toplink.jdbc.user" value="jpa"/>
              <property name="toplink.jdbc.password" value="jpa"/>
              <property name="toplink.jdbc.url" value="jdbc:derby://localhost:1527/JPAAssignments"/>
              <property name="toplink.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
              <property name="toplink.ddl-generation" value="drop-and-create-tables"/>
            </properties>
          </persistence-unit>
        </persistence>

    • Steps for execution
      1. Compile the source files
      2. Build the project
      3. Start the Database Server
      4. Execute the “EmpClient” class.
      5. Connect to the database & verify the table has been created & data is also added in the table.

    Advantages and Disadvantages of Using XML for Configuration



    • Advantages
      1. No coupling between the metadata and the source code
      2. Compatible with pre EJB3.0 development process
      3. Support from IDEs like NetBeans, Eclipse etc
      4. Easy to modify with the help of good editors.


    • Disadvantages
      1. Complexity
      2. Difficulty in debugging in absence of editors

     

    Wrap Up

    This article helps in understanding entity configuration with XML files as an alternative to embedding annotations in Java code for configuring persistence details.

 

 

 

 

Top