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).
Large Object:
No comments:
Post a Comment