Tuesday, March 27, 2012

Optimistic / pessimistic locking LockModeType

What is the difference between optimistic locking and pessimistic locking?
First of all locking is intended for managing transactions.
If transactions can run serial, that means one after another,
nothing can go wrong:
The transaction fulfills the ACID properties:
- atomic
- consistent
- isolated
- durable

From database view a transaction should always have these properties:
It is executed as a whole or not - atomic.
It drives the state of the database from one consistent state to another state - consistent.
Transactions do not influence each other - isolated.
Transactions and there changes are saved durably in the database  - durable.
From JPA or Hibernate view the easiest way is using the highest isolation level:
Serializable.
Serial transactions in high frequent systems have a bad performance and scalability.
Therefore the level of serialization of an application / system is reduced to increase performance and throughput.
You pay this by problems which occur on account of certain isolation levels:
  • Dirty Reads: Changes are read by other transactions before they are committed. If a rollback takes place you have read something wrong.
  • Non repeatable Reads: Rows are read, another transaction makes changes, rows are read again, other data exists as to begin of the transaction
  • Phantom Reads: a query delivers different results during a transaction
Normally you have some places in your application or system which have to handle transaction in a highly secure way. The business logic needs a high transaction security and this is payed by less performance.

How is transaction management done in JPA?
In JPA you normally have 2 scenarios:
  1. JEE - environment and existence of a JTA manager
  2. no JEE- environment and management of transactions by the application itself
Assuming point 2) the entity manager is used for the management of transactions:
the EntityTransaction- Interface, which is delivered by EntityManager.getTransaction().
Here you have the usually methods for transaction management defined:
  • begin()
  • commit()
  • rollback()
In the Spring-environment the transactions are managed by the annotation declared on the method declaration:
@Transactional(isolation=Isolation.READ_COMMITTED, propagation=Propagation.REQUIRED)

If the method is stated with @Transactional you have the behaviour like above:
the isolation level is set by the database default(usually READ_COMMITTED) and a transaction is needed.

Locking -strategies
JPA behaves like you know it from Hibernate already:
If an entity is annotated with @Version optimistic locking takes place for this entity.
Optimistic locking is the mechanism where objects are not explicitly locked at the beginning of a transaction.
It assumes that optimistically no conflict will take place. Therefore at the moment of persisting/writing on commit a version check takes place:
Every update on an entity increments the version of an entity.
The version - property of an entity can only be written by the JPA-provider.
On commit the entity is checked if it has a different version value.
If so, an OptimisticLockException is thrown.
If not the entity with the new version number is persisted in the database.
The OptimisticLockException should be handled by the application.
This behaviour is delivered by using @Version.
With Hibernate as the JPA-provider and setting the isolation level of the transaction on Repeatable Read or Serializable, the version checking is done explicitly with a select for the Entity for retrieving the actual version used in the database. This is the Hibernate specific LockMode.READ.
If the cache is used for version checking this corresponds to LockMode.NONE.
LockMode.UPGRADE corresponds to the JPA mode LockModeType.READ.

A more restrictive OptimisticLocking - mechanism can be configured by selecting the isolation level.
For that the objects which should be locked are locked by:
EntityManager.lock(object, LockModeType t);
If LockModeType.READ is set, normally during commit the corresponding object is locked by select .... from table for update:
on row level an exclusive lock is set, which is set for a very short time span.
There is LockModeType.WRITE which increments the version - also if nothing has changed on the entity.

Pessimistic Locking, that means locking of objects on transaction begin and keeping the lock during transaction is done by these 2 PessimisticLockModes:
- LockModeType.PESSIMISTIC_READ -->
entity can be read by other transactions but no changes can be made
- LockModeType.PESSIMISTIC_WRITE -->
entity can not be read or written by other transactions










Tuesday, March 20, 2012

Persist with JPA: persist(), merge(), remove(), clear(), close() or flush()?

Which JPA method should be used when?
JPA support some methods for working with the persistence manager:
  • persists()
  • merge()
  • remove()
  • flush()
  • close()
What happens during persist() / flush() / close?
On persist() the transient entity is attached to the persistence context, that means the entity has got a connection to the entity manager. This entity is not immediately represented in the database!
E.g. the transaction is rolled back on account of a sql error or an explicitly called rollback, than
the transient entity or changes made to other entities are not stored in the database:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistence");
EntityManager em = emf.createEntityManager();

...
em.getTransaction().rollback();
...

If you want to synchronize in dedicated places in your transaction code, you use flush().
What happens to detached entities on flush()? Nothing.
What happens to persistent entities, which are connected to transient entities? IllegalStateException
What happens to persistent entities, which are connected to detached entities?
The relationship to the detached entity is stored, if the persistent entity is owner of that relationship.

Normally on transaction end the changes made to the entities and new persistent entities will be stored in database by the JPA-provider.

On a close() the entity manager is closed like as on clear() and all entities are not more connected to the entity manager.
Those entities are now in the state detached and will not be synchronized with the database anymore.
To get synchronisation done you use the method merge().
With merge detached entities can put into persistence context again.
During that operation the entity which should be merged will be copied into the persistent entity.
If for a detached entity no persistent entity is found in the current session, the JPA-provider tries
to load the specific entity or if unsuccessfully it will be stored as a new entity.
An entity is removed from persistence context by calling remove() on the specific entity. On transaction end it will be deleted from the database.
If merge() is called on a already deleted marked entity an IllegalArgumentException is thrown.






Sunday, March 18, 2012

Hibernate 4.1 new features loading per @NaturalId

What features come along with the new Hibernate 4 Release?
In Release 4, to be correct 4.1-Release, one can load entities with naturalIds.

What are naturalIds?
NaturalIds are keys with professional uniqueness, which can be used in certain queries or loading situations. It is recommendate that technical keys are used, but if those entities have attributes with professional uniqueness, those attributs can be assigned hibernate annotations
@NaturalId. Those properties must be unique, because
an unique constraint will be created on that column in the database.


Why should I bother about @NaturalId - annotations anyway?
Assumpted that there is an entity taxpayer. It certainly has a property named taxnumber.
The taxnumber should be unique.
So this property is a candidate for a definition of an naturalId.

public class Taxpayer {
  @Id
  @GeneratedValue
   private Long id;
   private String firstname;
   ....
   @NaturalId
   private String taxnumber;
   ...
}

Now you have an advantage, which could be used already in older hibernate versions:
You can make use of those naturalIds in queries:
Session s = ...
Criteria crit = s.createCritera(Taxpayer.class);
Taxpayer t = (Taxpayer) crit.add(Restrictions.naturalId("taxnumber").set("89089083AST8908").uniqueResult();

New 4.1 feature:
With 4.1 you can define @NaturalId in the entity and use it on the session object, that means you
can load an entity with help of byNaturalId()!

Session s = ...
TayPayer t = (TaxPayer) s.bySessionId(Taxpayer.class).using("taxnumber", "89089083AST8908");


Is there an disadvantage?
Unfortunately, the @NaturalId is a hibernate specific feature.
So you can't express / use @NaturalIds in JPA.
It seems, that @NaturalId will not be included in the upcoming JPA 2.1 standard.
See: Early Draft JPA 2.1

Saturday, March 17, 2012

JPA find() vs. getReference()

How are persistent entities in JPA retrieved?
Here are 2 possibilities besides other query calls:

  • find()
  • getReference()
How are they used?
- Find() is called on the EntityManager and the method needs 2 parameters:
  1. Type of the wanted entity
  2. Identity: Id of the wanted entity
Caller gets the retrieved entity or null.
Example:
EntityManagerFactory ef = Persistence.createEntityManagerFactory("myapp") ;
EntityManager em =  ef.createEntityManager();
....
Client k = em.find(Client.class, 70992);


- GetReference() is used similarly.
Client k = em.getReference(Client.class, 70922);
If the entity for the stated id is not known in the persistence context, an EntityNotFoundException() is thrown.

What is the difference between both methods?
Find() delivers the entity from the cache of the persistence context or if he is not there, it will be loaded from the database.
GetReference() does not load the entity immediately. A proxy( a certain object, a so called "deputy" with enriched methods for loading the actual entity) is returned. So it is a realisation with help of LazyLoading.
Only if the attributes of the proxy or other persistence methods are needed/called the proxy interacts and loads the actual entity from the database.

When should one use which method?
The usage of find() should take priority over query methods, because find() can return already loaded entities from the cache of the persistence context.
If you do know, that an entity is need later on, the usage of getReference() is a good choice.

Friday, March 16, 2012

JPA life cycle transient persistent detached

What is the life cycle of a JPA entity?
If an entity has been defined, later on instantiated, than the life cycle of the entity begins.
The life cycle of an entity ends with remove() or a detach() (see below) method call.
An entity does not know its state of the current life cycle.
So it cannot be be queried to retrieve it's state.


What states does a JPA entity has in its lifespan?
  • transient
If a class was defined with @Entity, than  the class is an entity, so it will be used later on in the persistent context and will be managed by the Entity Manager.
As soon as this class is instantiated, it has the state transient, that means it is still a POJO, but
it will not be synchronized with the database.

  • persistent
If the method persist() is called with this entity, the entity is placed into the persistence context, that means a connection between entity and entity manager has been established.
The entity will be synchronized with the database on transaction end(commit() or flush()).

  • detached
If an entity is removed from the persistence context with the help of detach() or if the EntityManager was closed, then the connection(see above persistent) is removed. Therefore the entity will not be synchronized any longer in all cases.

A detached entity is integrated into the persistence context on calling merge().
A persistent entity can be turned into the state transient with the help of remove(), the corresponding data in the database will be deleted.


Wednesday, March 14, 2012

JPA2 Feature Saving the order of elements of an association

In JPA 2 there is a new feature for assuring that an association has always the same order of elements.
That means the order of the elements of an association, which is realized by a list, is stored in the database as well.
There is a 1:n - association.
The 1-side has the according collection of entities of the n-side.
This collection can be defined as list in the specific entity class.
If you want, that the list behaves deterministic, that the order must be stored:
therefore you can use the new annotation in JPA 2:

@OrderColumn

@Entity
public class A implements Serializable {
   ...
   @OneToMany
   @OrderColumn
   private List<B> bs = new ArrayList<B>();
   ...
}    

@Entity
public class B implements Serializable {
 ...
 @Id
 @Generated
  private Long id;
  private String orderNumber;
 ...
}

In this case in the entity B a new field with the name BS_ORDER is created, which can not be seen by the entity itself. It is used for saving the order of the associated entities of B to A.
So the order of elements of the collection is always the same, when the entities of A are load for e.g. with mode FetchType.EAGER.
When would you use it?
If the sort order @OrderBy has an bad impact on access execution or the order of subject-specific attributes / columns still produces an undefined order.


Saving of elements per key of an association, which is realized by Map, was possible in the previous JPA Version:
In the example above bs is not created as List, but as Map.
Then the annotation @MapKey can define the key with whom one can access the collection / association.
The Default @MapKey always defines the primary key of the entity for accessing the map.
If you want to use another column as the key, you can use the parameter name:

@MapKey(name="columnName").
The result of the above example is:
   @OneToMany
   @MapKey(name="orderNumber")
   private Map<String, B> bs = new HashMap<String,B>();

For what do we need an key based access of an association?
It makes sense, if you know, that the access of this annotation regarding the business logic
usually is done per using the orderNumber and the primary key is a more technical key, which is used in other subordinated use cases like archiving the data.
So one can express very clean:

String aOrderNumber;
....
B myBEntity = a.getBs().get(aOrderNumber);


Tuesday, March 13, 2012

Treatment of Value Types in JPA Hibernate

How is value types approached in JPA / Hibernate?

First of all the definition of value types.
Value types are no real entities. They have no life cycles, that means they will not be created, later on edited or deleted. They exist since beginning of system life.
True entities, which are marked with @Entity, do have a life cycle and they a corresponding representation in the database.
Now there a certain cases in which one wants to use value types:

  • as constants, which are stored as attribute to a entity in the database
  • values, which are stored next to a certain entity
Constants can be made easily in Java with enums:
public enum EnumXY{
   constantValue1, constantValue2, constantValue3;
}

They are used with every entity:
@Entity
public class MyEntity implements Serializable {
    ...
    @Enumerated
    private EnumXY flag;
    ...
}

In the table per default the position of the value(ordinal number) of the corresponding entity is stored as integer. If the MyEntity flag gets the constantValue3 assigned, than value 2 is stored in the table of MyEntity.
This can be configured with @Enumerated(EnumType.ORDINAL) (default) or @Enumerated(EnumType.STRING). The latter the name of the constant will be stored in the corresponding column of the database table. Here it is constantValue3.

What happens if someone wants to store multiple values of a value type to an entity?
This is also possible in JPA 2:
With the help of @ElementCollection you can express, that the collection is made of values of a value type and not a collection of normal entities.
 @ElementCollection
private List<String> basetypeValues = new ArrayList<String>();
First of all  CollectionsOfElements is the hibernate specific annotation.
In JPA you should use @ElementCollection.
Example:
@Entity
public class X implements Serializable {
  @Id
  @Generated
  private Long id;
  @ElementCollection
   private List<String> remarks = new ArrayList<String>();
    ...
}

@Test
public void testElementCollection() {
  ...
  X x = new X();
  private List<String> remarks = new ArrayList<String>();
  remarks.add("remark1");
  remarks.add("remark2");
  remarks.add("remark3");
  x.setRemarks(remarks);
  em.persist(x);
  ...
}

What happens in the database?
An "ElementCollection" will always be stored in a separate table.
This can be defined more precisely with @CollectionTable. JoinColum(s) is used for the definition of the foreignKey(s):
@CollectionTable(
   name = "nameOfCollectionTable",
   joinColumns = @JoinColum(name="fk")
)

Result:

Table X:
id column1 column2
3 .....         ....

Table Remarks:
id remarks 
3  remark1
3  remark2
3  remark3