About Transparent Persistence
Here's an overview of transparent persistence in action and why it can be an invaluable concept. Go through the steps of setting up your own persistent ORM.
Join the DZone community and get the full member experience.
Join For FreeWhen you are developing in the object-oriented paradigm and you have to persist your objects via relational storage, there are, basically, two ways of doing it: using an ORM or using the database connectivity API that the language provides. What is the factor when choosing between one or the other?
Talking now in terms of the Java programming language, what makes you choose Hibernate over JDBC? Is it their Criteria API? HQL?
I personally use Hibernate because of their Transparent Persistence support. That is the real beauty. Let me explain what I mean.
The goal of an ORM is to let you design your application without worrying about a persistent mechanism. Design your domain model, implement it and test it, and just persist it on volatile memory. The ORM tool, after it's configured, will take care of persisting your objects in a persistent storage.
Let's illustrate the previous sentence with an example using a common problem domain: Organizations. Let's model Departments and Employees, where departments have members that are their employees. I would write the following two classes (simplified):
public class Department {
private String name;
private Collection employees = new ArrayList<>();
public Department(String name) {
this.name = name;
}
public void addEmployee(Employee m) {
employees.add(m);
}
public int totalEmployees() {
return employees.size();
}
}
public class Employee {
private float salary;
private String name;
public Employee(String name, float salary) {
this.name = name;
this.salary = salary;
}
public String name() {
return this.name;
}
public float salary() {
return this.salary;
}
}
And a test to cover that piece of functionality:
@Test
public void a_new_employee_is_added_then_it_increments_the_total() {
Department sales = new Department("Sales");
Employee jorge = new Employee("Jorge Dalmiro", 1239f);
sales.addEmployee(jorge);
Assert.assertEquals(1, sales.totalEmployees());
}
An ORM like Hibernate will let you write something like the test above and make the relation between the employee jorge and the sales department persistent — isn't that great?
You may be asking, "I don't have to deal with the save or store method of the ORM API? I don't have to write any SQL statement?" No! you have to just write code like this:
department1.addEmployee(new Employee("José", 10503f));
Then José will be persisted and be part of department1.
The real beauty of an ORM is the transparent persistence that provides, which will let you write plain Java objects and make them persistent with little work.
Transparent Persistence
To understand how transparent persistence works, we have to understand two main concepts. The first one is called Persistence Context. The Persistence Context is the place used by the ORM to keep track of the changes of your instances in order to persist them at a later point. In the Java Persistence API, this context is managed by the javax.persistence.EntityManager class. Each Java Object in a persistence context will have one of these states:
- New, or transient: The object has just been instantiated and is not associated with a persistence context. It has no persistent representation in the persistent storage.
Persistent: The object is associated with a persistence context and has representation in the persistent storage.
Detached: The object is no longer associated with a persistence context (usually because the persistence context was closed).
Removed: The object is associated with a persistence context. However, it is scheduled for removal from the persistent storage.
The other important concept is called Persistence by Reachability, which states that any transient object that gets related to a persistent object will become persistent, too.
These two concepts are implemented in an ORM to make possible so-called Transparent Persistence.
Let's put these concepts in code.
EntityManager em = //obtain the EntityManger instance
EntityTransaction tx = //obtain the EntityTransaction instance
try {
tx = em.getTransaction();
tx.begin();
Department dept1 = em.find(Department.class, "department1");
dept1.addEmployee(new Employee("José", 10503f));
tx.commit();
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new RuntimeException(e);
} finally {
em.close();
}
On line 8, I'm getting the Department department1 from the persistent storage and, on line 9, just appending a new employee to it. Due to the fact that department1 is in the persistent state, by reachability the transient instance of Employee (José) will be persisted and attached to the department.
Let's write something a bit richer. Suppose now that I have the following new requirements. Each department gains 5 points each time a woman joins them and 3 points for men. Also, each department loses 5 points when an employee leaves them. I would change the Department class in the following way:
public class Department {
...
private int points;
public void addEmployee(Employee e) {
points += e.points();
employees.add(e);
}
public void removeEmployee(Employee e) {
points -= 5;
employees.remove(e);
}
...
}
Now, if I add an employee to a department:
//start persistence context
...
Department dept1 = // retrieving from the storage
dept1.addEmployee(new Employee("Julio", 6205f));
...
//close end of persistence context
In addition to persisting the new Employee and the relation with the department, it will also persist the new points obtained by adding employees to the department. It will be done by executing two SQL statements wrapped in a transaction. Something like:
insert into employees values("Julio", 6205f, "department1");
update departments set points = ? where id = "department1";
That was transparent right? You can visualize all the work done by the ORM for you. This means that you can focus the effort on making a good Object Domain Model (and by good I mean with business logic inside and not an anemic model), test it on memory, get a high test coverage, and let the ORM take care of the persistence.
The support of Transparent Persistence is what makes Hibernate (and others) an invaluable tool.
Opinions expressed by DZone contributors are their own.
Comments