Hobione's Weblog

Living & Breathing in Web 2.0 Era

Java Persistence API Pro

Book Reference: Pro EJB 3: Java Persistence API (Pro)

Chapter 1

Why Persistence?
As all we know that understanding the relational data is key to successful enterprise development. Moving data back and forth between to database system and the object model of a Java application is a lot harder than it needs to be. Java developers either seem to spend a lot of time converting row and column data into objects, or they find themselves tied to proprietary frameworks that try to hide the database from the developer. The Java Persistence API is set to have a major impact on the way we handle persistence within Java. For the first time, developers have a standard way of bridging the gap between object-oriented domain models and relational database systems.

Java Object – Database Relational Mapping:
The main thought behind to convert JDBC result sets into something object-oriented as follows.
” The domain model has a class. The database has a table. They look pretty similar. It should be simple to convert from one to the other automatically” The science of bridging gap between the object model and the relational model is known as object-relational mapping, aka O-R mapping or ORM.

Inheritance (Life is a dirty beach without JPA):
A defining element of an object-oriented domain model is to opportunity to introduce generalized relationships between like classes. Inheritance is the natural way to express these relationship and allows for polymorphisms in the application. When a developer start to consider abstract superclasses or parent classes with no persistent form, inheritance rapidly becomes a complex issue in object-relational mapping. Not only is there a challenge with storage of the class data, but the complex table realtionship are difficult to query efficiently.

JPA saves our soul (SOS):
The Java Persistence API is a lightweight, POJO-based framework for Java persistence. Although object-relational mapping is a major component of the API, it also offers solutions to the architectural challenges of integrating persistence into scalable enterprise applications.

Overview: JPA = Simple + elegant + powerful + flexible
Natural to use and easy to learn.

POJO: It means there is nothing special about any object that is made persistent. Java Persistence API is entirely metadata driven and it can be done by adding annotations to the code or using externally defined XML.

Non-Intrusiveness: The persistence API exists as a separate layer from persistence objects. The application must be aware of the persistence API, the persistence objects themselves need not be aware.

Object Queries: Query Language that derived from EJB QL and modeled after SQL for its familiarity, but it is not tied to the database schema. Queries use a schema abstraction that is based on the state of an entity as opposed to the columns in which the entity is stored. It returns results that are in the form of entities that enable querying across the Java domain model instead of across database tables.

Mobile Entities:

Simple Configuration:

Integration and Testability:

Chapter 2

Entity Overview: The entity is not a new thing. In fact, entities have been around longer than many programming languages and certainly longer than Java. Peter Chen who first introduced entity-relational modeling (1976) described entities as things that have attributes and relationships.

Here is an example of an Entity class from a regular Java Class:


package examples.model;

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

@Entity
public class 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;
    }

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

To turn Employee into an entity we first needed to annotate the class with @Entity. This is primarily just a marker annotation to indicate to the persistence engine that the class is an entity. The second annotation was needed to use as the unique identifying key in the table. All entities of type Employee will get stored in a table called EMPLOYEE.

Entity Manager: Until an entity manager is used to actually create, read or write an entity, the entity is nothing more than a regular (non-persistent) Java object. An entity manager is the show for the game. The set of managed entity instances within an entity instances withing an entity manager at any given time is called it’s persistence context. Only one Java instance with the same persistent identity may exist in a persistence context any any time. For example, if an Employee with a persistent identity (or id) of 158 exists in the persistence context, then no other object with its id set to 158 may exist within that same persistence context. All entity managers come from factories of type EntityManagerFactory. For Java SE application should use EntityTransaction instead of Entity Manager.

Obtaining an Entity Manger: The static createEntityMangerFactory() method creates EntityManagerFactory from persistence unit name “EmployeeServices”:


EntityManagerFactory emf =  Persistence.createEntityManagerFactory("EmployeeService");

Now we have a factory, we can obtain an entity manager from it:

EntityManager em = emf.createEntityManager();

Persisting an Entity: Insert. It creates a new employee and persist it to the database table


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

Finding an Entity: Read

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

In this case where no employee exists for the id that is passed in, when the method will return null, since that is what find() will return.

Removing and Entity: Delete

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

Updating an Entity: Update

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

Queries: Instead of using Structured Query Language (SQL) to specify the query criteria, in persistence world, we query over entities and using a language called Java Persistence Query Language (JPQL).
A query is implemented in code as a Query object and it constructed using EntityManger as a factory.
As a first class object, this query can in turn be customized according to the needs of the application.
A query can be defined either statically or dynamically (more expensive to execute). Also there is kind of query called named query as well.

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

To execute the query, simply invoke getResultList() on it and this returns a List. Note that a List <Employee> is not returned b/c no class is passed into the call, so no parameterization of the type is able to occur. The return type is indirect by the persistence provider as it processes the JPQL String. By doing this ( Collection<Employee> ) to make a neater return type.

Chapter 3

EJB definitions:

Chapter 4

Object-Relational Mapping

Lazy Fetching: The data to be fetched only when or if it is required is called lazy loading, deferred loading, lazy fetching, on-demand fetching, jun-in-time reading, indirection. Data may not be loaded when the object is initially read from the database but will be fetched only when it is referenced or accessed. The FetchType could be LAZY or EAGER. Lazy = until it is referenced. The default is to eagerly load all basic mappings.


package examples.model;

import static javax.persistence.FetchType.LAZY;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;

@Entity
public class Employee {
    @Id
    private int id;
    private String name;
    private long salary;

    @Basic(fetch=LAZY)
    @Lob @Column( name = "PIC" )
    private byte[] picture;

    public int getId() {
        return id;
    }

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

@Basic annotation is required. The comments field to be fetched lazily will allow an Employee instance returned from a query to have the comment field empty.  It will be transparently read and filled in by the provider (Toplink/Hibernate) once the comments filed get accessed.

Two things to be aware of.
First and foremost: The directive to lazily fetch an attribute is meant only to be a hint to the persistence provider to help the application achieve better performance.  The provider is not required to respect the request, since the behavior of the entity is not compromised if the provider goes ahead and loads the attribute.

Second: It may appear that this is a good idea for certain attributes but it is almost never a good idea to lazily fetch for simple types.  The only time when lazy loading of a basic mapping should be considered are when either there are many columns in a table (for example, dozens or hundreds) or when the columns are large (for example, very large character strings or byte strings).

Transient: My most favorite annotation. It uses like this, @Transient. Various reason we use transient but mainly for non-persistent case. We use transient to cache data in-memory state that you do not want to or have to recompute or reinitialize. Here is an example. I have a Customer table which has id, fname, lname, phone etc column. So, in my Model object I do as follows:

@Entity
public class Customer{

@ID
public Integer getId(){
   return id;
}
// ... setID(Integer id)

@FNAME
public String firstName(){
  return firstName;
}
// ... setFirstName (String firstName);

/*Customer class ties with Customer table. Now question is how can I write a get method that will return first name and last name together but wont break persistence rules. Here is how. */

@Transient
public String getFirstAndLastName(){
   return this.getFirstName() + " " + this.getLastName();
}

}

9 Comments »

  1. Hi

    Thank you for your examples (Chapter 4), I found what I was looking for quickly and clearly.

    Keep up the great work!

    Best regards,
    TungstenX

    Comment by TungstenX | July 9, 2008 | Reply

  2. Thank you!!, Obi-Wan
    Very good article!! Thanks for sharing the technology with us. Keep it UP!!

    Comment by naren | August 1, 2008 | Reply

  3. Thank you….. and just a smalle quesion… in the JPQL who queries the DB. Oracle(DB) it self or java.! does JPQL supports all the SQL functions.. ?

    does JPQL has a performance hit whn put to getther with JDBC..
    ?

    Comment by asitha | August 10, 2008 | Reply

  4. I believe in the JPQL, ORM engine does the query. It depends what ORM API you’re using so ultimately Java does the queries.

    I don’t think JPQL supports all the SQL functions.

    Hope this help
    Hobi

    Comment by hobione | August 13, 2008 | Reply

  5. When I use the @LOB annotation it always creates only VARCHAR(255) for stringData and Binary (255) for binaryData defined below.

    @Lob @Basic(fetch=FetchType.LAZY)
    private byte[] binaryData;

    @Lob @Basic(fetch=FetchType.LAZY)
    private String stringData;

    Any help in resolving this would be VERRY!!! appreciated.

    THANKS

    Comment by Patrick Walter | January 15, 2009 | Reply

  6. Hi HobiOne Master of Jedi and JavaEE.

    I have a couple of question for you and hope you can use your force to help me with this issue. I’m at the end of my degree in Computer Science but need your help very much indeed!

    Just completed my web site with Java EE-Netbeans 6.5 using JSP’s, JavaScript and HTML running on Glassfish.

    I bought my own domain from a third party, but, would like to run and host my website at my location. I’m half way through my second web site which will use the full power of JavaEE from Servelets, JSP’s, EJB’s, JavaBeans and Transfer Objects. However, I would also like to run it at my location on my own server.

    Moving forward, I had a look at your comments with regards to setting up a virtual server on Glassfish using listener-3 and port 80. However, when I restart my computer I’m unable to communicate with GlassFish. Therefore, I have had to unistall it twice, but still unable to get it to work.

    I believe the steps are the follow if my web site is to be called http://www.xyandz.co.uk:

    1st-Create a virtual server
    -id = xyandz
    hosts= xyandz.co.uk
    HTTP Listeners = http-listener-3
    Remainig fields left unchanged as I’m not sure what to put in them.

    2nd- create the listener:
    name= http-listener-3
    Network Address = My actual PC IP Address
    Listener Port = 80
    Default Virtual machine = xyandz
    Server name = (I’m not sure)
    Remainig fields left unchanged as I’m not sure what to put in them.

    Still, I’m unable to deploy (bind my computers IP to my purchased domain name) my project to the internet.

    The main web page is called login.html, there are around 30 other HTML pages, graphics, JavaScript, CSS which link up to a Servlet called Servlet2 to respond to requests and save data in a simple CSV file.

    PS:
    I currently have assigned a Dynamic IP address for my computer at home and would like to build a proxy to mask my IP address and route all communications to my PC—Can you help with this?

    You mentioned we need to contact the domain provider with regards to ask them to make some changes to the DNS –Can you also help with this?

    I would very much appreciate if you could read my posting and comment on it too.

    Thanking you in advance
    regards
    J Marks

    Comment by J Marks | May 15, 2009 | Reply

  7. Hello J:
    First of all, you need to have a static IP in order to run a web/app server. You can mask it by using DynDNS or similar program but using static ip gives you stable connection with server. Once you get that, just follow this link https://hobione.wordpress.com/2008/10/02/glassfish-virtual-server/
    You should be good to go.
    Best regards,
    – Hobi

    Comment by HobiOne | May 15, 2009 | Reply

  8. Hi,

    Wondering if you worked with EntityListener when an entity is lazy loaded ? somehow the callback methods are not invoked during the lazy loading.

    Any help is appreciated.

    Comment by Srinivas | August 5, 2009 | Reply

  9. Thanks for share. Here have other tutorial about javabean

    http://codeoop.com/2011/05/19/javabeans-p2/

    Comment by codeoop.com | July 13, 2011 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: