Introduction

JAVA Line is a systematic introduction to Java EE 6 concepts for those who are familiar with Java Enterprise concepts. Besides, it is a collection of fast tips to be referenced quickly by Java Enterprise developers.
Most of the tips are based on the book 'Beginning Java EE 6 Platform with GlassFish 3 From Novice to Professional'. Please subscribe to get the latest updates.
The following are the current topics;

JEE6 Fundamentals

Why JEE6?
Lighter, easier to use, richer and more portable.
JEE is an umbrella specification and JEE6 contains 28 specifications. For further info visit here.

Why not J2EE?
Difficult to test, deploy and run.

Non-standard frameworks
Most successful Java frameworks are not standardized. As an example, Struts, Spring and Hibernate frameworks are not portable across different application servers.

Other emerging techs by rising of JEE6
JAX-WS 2.2 replaced JAX-RPC for SOAP web servises.
Entity Beans replaced for JPA.
JAXR, JEE Application Deployment, JEE Managment.

Supported network protocols
JEE6 supports HTTP and RMI-IIOP. Therefore a good substitute to CORBA technology.

Current Application Server
The current JEE6 application server is GlassFish v3.
An application run on Tomcat should run unmodified on GlassFish.

JPA 2.0





JPA
Java Persistence API 2.0, is the persistence framework in JEE6 to manage relational data and is preferred to ORM(Object Relational Mapping) tools.
JPA 2.0 support the following new features;


  • Collection of simple data types(Integer, Long, ...)

  • Map support with value of basic types, entities or embeddables

  • Persistent ordering(@OrderColumn)

  • Orphan removal

  • Optimistic/pessimistic locking

  • Embeddable objects nested into other embeddables


Reference Implementation
EclipseLink 1.1 is the RI for JPA 2.0. It is a persistence provider.


Persistence Unit
The descriptor file for the Persistence Unit is located in resources\META-INF\persistence.xml in each project. It links the JPA provider to the database through special tags. For example the provider tag contains the persistence provider class and the data-source contains the data-source which is defined on the application server as a JNDI name to database. It also contains all the entities that will be managed by the persistence unit (each entity is defined through class tag).


Variable Mappings
Variable mappings are different among databases. For example, in Derby database, variable mappings are as follows;

  • Long <-> bigint

  • String <-> varchar(255)

  • Float <-> double

  • Integer <-> integer

  • Boolean <-> smalint


JPA Unit Testing
You can test entities without any required running application server or live database.

  • Useful to test queries

  • Uses an in-memory database and non-JTA transactions by including a jar file to the class path

  • The embedded database is run in the same process

  • Applicable to embedded mode of Derby


Important Annotations

  • @javax.persistence.Entity (Must be applied on the entity class)

  • @javax.persistence.Id (Applied on the primary key)

  • @javax.persistence.GeneratedValue (Applied on the primary key to automatically generate pk values)

  • @javax.persistence.Column (Applied on an attribute to customize the default column mapping)


Musts for Entity Classes

  • At least one no argument, public/protected constructor

  • To be a top level class (not an enumeration/interface)

  • The entity, its methods and persistence variables must not be final.

  • If an entity instance has to be passed by value as a detached object, the entity class must implement the Serializable interface.


Entity Attribute Types

  • Java primitives and their wrappers

  • byte[], Byte[], char[], Character[]

  • String, BigInteger, BigDecimal, Date, Calendare, TimeStamp

  • Enumerated and user-defined types that implement Seriallizable

  • Collection of basics and embeddables

  • Entity

  • Collection of entities/embeddables


Basic Annotations
The most common annotations in JPA are as follows;

  • @Table
    Used to specify the name of the table, catalog, database schema or unique constraints
    example:
    @Entity
    @Table(name="Book_Table")

  • @SecondaryTable
    Used to spread data over multiple tables (columns can be selectively selected by @Column to be inserted in a specified table)
    example:
    @Entity
    @SecondaryTable(name="secTab")
    .
    .
    .
    @Column(table="secTab")

    This leads to creation of different tables containing different attributes but with the same primary key. It is useful when there are expensive attributes (like BLOBs) but has performance issues.

  • @Id
    The annotated attribute cannot be updated once assigned.
    Applicable to primitives (byte, int, short, long, char) and their wrapper types and arrays of them.
    Applicable to String, BigInteger, util.Date, sql.Date

  • @GeneratedValue
    The value of the identifier attribute can be generated automatically.
    Strategies:
    • Sequence
      Database sql sequence

    • Identity
      Identity column

    • Table
      Sequence is stored in another table

    • Auto
      Strategy is decided by underlying database.


  • @Basic
    It has two parameters; optional (sets if the value of the property can be null) and fetch (contains two modes: LAZY; indicates to load data when needed and EAGER; causes data to be initially loaded)

  • @Lob
    It is used (to inform the provider) for attributes that store large objects.

  • @Column
    Specify column-name, size, null allowed, uniqueness, updatability, insertability, etc. for an attribute. Most of these elements have an influence on the mapping.
    Setting 'insertable' and 'updatable' has effect on the generated SQL statements to include the attribute or not.

  • @Temporal
    It is used for date/time attributes. It accepts DATE, TIME or TIMESTAMP as an argument to provide different kind of date/time mappings.

  • @Transient
    Use it to refuse an attribute to be mapped to the database (useful for derived attributes).

  • @Enumerated
    Useful in storing enums as the attributes.
    ORDINAL (default): Values are passed by their location in enum in int type.
    STRING : Values are passed by their name. It is the preferable strategy in most situations.

  • Composite Primary Keys
    • @EmbeddedId
      Refers to the class which is marked with @Embeddable
      The Embeddable class does not have any identity of its own and its columns end up as columns in the table of the entity that contains it.
      The Embeddable class must have a no-arg constructor, accessor methods (getters & setters) and override equals() and hashcode() methods properly. It must not contain @Id annotation also.
      An example of querying from a class containing an @EmbeddedId attribute in JPQL is;
      SELECT b.bookId.title FROM Book b
      where bookId refers to Embaddable class (Composite Primary Key) and title is an attribute in such class. Book is the class declaring an attribute of Composite Primary Key.

    • @IdClass
      This annotation must be provided with a Class parameter (e.g., @IdClass([class-name].Class)). The parameter is the composite-primary-key-class which contains the declarations of primary keys and overrides equals() and hashcode() methods properly.
      The main class has to annotate each key (defined in parameter class) with @Id annotation.
      There is no need to modify the composite-primary-key-class but the mechanism is more prone to error.
      An example of querying from a class containing an @IdClass attribute in JPQL is;
      SELECT b.title FROM Book b
      As you see, the composite primary keys are mapped to fields/properties of the entity.


Access Types
In many cases when there are different entity classes, mapped superclasses, or embeddable classes with different access types and there is inheritance or some embeddings defined, its is strictly suggested to define the access type explicitly.
There are two different access types;

  • Field-based; annotate the attributes (fields)

  • Property-based; annotate the properties (accessor method of the filed)

The access type is defined at class, method or field level by @javax.persistence.Access annotation with AccessType.FIELD or AccessType.PROPERTY as parameter.



Relationship
In JPA, relationship is achieved when one entity has a collection of other entities or embeddables.


Collection of Java Basic Types

  • @ElementCollection
    Used to indicate an attribute of type Collection contains Java types.

  • @CollectionTable
    Used to customize the details of the collection table.
    Default table name is the concatenation of the name of the containing entity and the name of the collection attribute, separated by an underscore.


Map of Java Basic Types
Maps can contain any combination of basic types, Embeddable objects and entities as key or value.
In addition to @ElementCollection and @CollectionTable, use @MapKeyColumn to specify the mapping for the key column of the Map collection. The default name for the key column is 'the name of the referencing relationship attribute' attached to '_KEY'.


Embeddable
The Embeddable object is one that does not have a persistent identity of its own. The owning entity could have a single Embeddable attribute or collections of Embeddables.
There are two annotations to make use of Embeddable objects;

  • @javax.persistence.Embeddable, annotates the Embeddable class.

  • @javax.persistence.Embedded, is used in the owner class to include the Embeddable.

Note that, if the access type is not explicitly set, the access type of the embeddable class is determined by the access type of the entity class in which it is embedded. Therefore, to avoid mapping errors, use explicit access type on embeddables.



Relationship Mapping
Navigation in Association

  • Unidirectional
    One object can navigate toward another.

  • Bidirectional
    One object can navigate toward another and vice versa.

Cardinality in Association
  • In Java, an association that represents more than one object uses Collection, Set, List or Map.

  • OneToOne, OneToMany, ManyToOne and ManyToMany are the association cardinalities.

Ownership in Association
Each relationship in Java must have an ownership. The owning-side is by which the physical mapping is specified. This means that the owning-side defines relationship.
Each cardinality can be used with each direction.
  • Ownership in unidirectional relationship is implicitly maintained.

  • Ownership in bidirectional relationship must be specified explicitly.


Reference Models
Implementing the relationship between two entities is maintained in two ways;

  • Join Column
    The owner-side-entity contains the join-column-property (foreign key). The join-column-property is the identity-column (primary key) of the inverse-side-entity.

  • Join Table
    A separate join-table containing the identity-property of both relationship sides is maintained.


Ownership in Bidirectional Relationship
The 'mappedby' element of @OneToOne, @OneToMany, @ManyToMany must be specified in the inverse-side-entity to identify the attribute that owns the relationship. This means the 'mappedby' element must be specified in the entity which is mapped to the underlying table that does not contain the foreign-key (join-column).


Fetching Relationships

  • Eagerly; Loading data from database to memory when entity is initially read. This brings all data into memory using small amount of data access.
  • Lazily; Loading data from database to memory when entity is accessed (e.g., through getter method). This way, you don't risk to fill up the memory but you have to access database every time.


OneToOne Relationship (Unidirectional)
Simply, insert the attribute of the target-entity in the owner-entity. The join-column (FK) of the inverse-entity (target-entity) is placed in the owner-entity. By default, the join-column can be null.
To customize the mapping use @OneToOne or @JoinColumn (or both). @OneToOne is used to customize the association and @JoinColumn is used to customize the join-column mapping.


OneToOne Relationship (Bidirectional)
The implementation is the same as OneToOne unidirectional but with a simple modification in the inverse-side-entity. The inverse-entity must have an attribute type of the owner-entity, annotated with @OneToOne. The 'mappedby' element in this annotation must be specified with the owner-entity attribute (join-column) name.


OneToMany Relationship (Unidirectional)
Simply, place a collection of target-entity in the source class. This relationship is through join-table by default but this can be modified. The following annotations can be applied for customization;
@OneToMany customizes the relationship.
@JoinTable can be used to customize the join-table.
As an alternative to join-table (instead of @JoinTable), you can use @JoinColumn to define the relationship through a FK column in the target-entity.


OneToMany (Bidirectional) and ManyToOne Relationships
In the owner-side, @ManyToOne and @JoinColumn annotations must be specified on the join-column (FK). It is possible to use @JoinColumns if there are more than one identity-attribute (PK) in the inverse-entity (discussed below in 'Note').
In the inverse-side, @OneToMany must be specified on the collection attribute of type owner-entity. The 'mappedby' element in this annotation must be set to the attribute in relationship of the owner-side. As discussed previously, the 'mappedby' element is always used in the inverse-side to tell the provider, the name of the corresponding attribute in owning entity.

Note: In case there are multiple identity-attributes in the inverse-side, the owner-side must use @JoinColumns.

In bidirectional relationships, if there are many identity-attributes (e.g, composite primary key) in the inverse-side, there must also be many join-attributes (FK) defined in the owner-side. This is done through @JoinColumns. It means a @JoinColumn must be specified for each join-column (FK) and every @JoinColumn is nested inside @JoinColumns.
The 'name' and 'referencedColumnName' elements should be specified for each @JoinColumn. 'name' can be everything (most not conflict with other names) and 'referencedColumnName' must be exactly the name of the mapped column of the inverse-entity to the database (the mapped name).


ManyToMany (Unidirectional)
The ManyToMany association cannot be bidirectional and is controlled only by the owner side. Anyway, the mappedby element is used to define the owner side.
The join-column mechanism does not work hear therefore the join-table is considered.
@JoinTable is used for customizing the join-table at the relationship attribute (collection) in the owner side (to define the join-columns and inverse-join-columns) and the mappedby element is specified in @ManyToMany at the relationship attribute (collection) in the inverse side. If mappedby is not set, two separate one to many unidirectional relationships will be made.


Ordering Data

  • Dynamic ordering;
    • use 'ORDER BY' in JPQL
    • sort a Collection programmatically through @OrderBy
  • Persistent ordering;
    @OrderColumn is used on the Collection to maintain an ordered list in database through defining an additional column in the underlying table (performance impact).
@OrderBy and @OrderColumn cannot be used at the same time.


Inheritance Mapping
There are three possible inheritance mapping strategies that can be declared through @Inheritance annotation on root (super) class for once to dictate the mapping strategy to root class and its child classes.

  • Single table per class-hierarchy (SINGLE_TABLE)
    It is the default inheritance mapping therefore there is no need to annotate the root class to apply this mechanism.
    All entities in the same hierarchy are mapped to the same table.
    A new discriminator column (DTYPE) of type string is added to the underlying table. Use @DiscriminatorColumn to modify this column.
    @DiscriminatorValue is used on each entity when discriminator type is set to CHAR in @DiscriminatorColumn.

  • Joined subclass (JOINED)
    Each entity (concrete or abstract) is mapped to its table.
    Root entity defines the primary key to be used by all tables as well as a discriminator.
    Each subclass contains its own attributes (not inherited from root) and a primary key which refers to the root table's primary key.
    @DiscriminatorColumn and @DiscriminatorValue are also applicable.
    This mechanism has performance impact on querying.

  • Table per concrete class
    The most complicated mechanism in which each concrete class is mapped to a table.
    All tables must share a common primary key that matches across all tables in the hierarchy.
    Use @Table to customize each table.


Note: @AttributeOverride(s) is used in leaf classes of an inheritance hierarchy or the classes that have embeddables to override inherited attributes. For example;
@Entity
@@AttributeOverrides({@AttributeOverride(name = "id", column = @Column(name = "Item_ID", ...})


Types of classes in the Inheritance Hierarchy

  • Abstract Entity
    • They must follow mapping strategies.
    • They are mapped as an entity.
    • They cannot be directly instantiated.
  • Non-Entity
    • They are called transient classes or POJOs.
    • They are not managed by provider.
    • An entity may subclass or be extended by a non-entity (Only entity attributes get persisted).
  • Mapped Super Class
    • They are not entities (not managed by provider).
    • They can be used to share state, behavior, and mapping information (to child entities).
    • They cannot be part of a relationship.
    • They are similar to embeddable classes except that they can be used in inheritance.
    • They are annotated with @MappedSupperClass and not @Entity.
    • @Table is not permitted.
    • They cannot be queried or persisted.
    • All the customized mappings (annotations) are inherited (exposed to childs).


Entity Manager
It is an interface implemented by the persistence provider to manage the state and life-cycle of entities as well as querying them.
When an entity manager method is invoked, the persistence provider generates and executes a SQL statement through the corresponding JDBC driver.
When the entity manager obtains obtains a reference to an entity, the entity is said to be managed. In this state, the entity manager will automatically synchronize the state of the entity with the database (It works on per-transaction basis to reduce the number of SQL queries within a transaction).
Contrary to application managed environment (transaction-type="RESOURCE-LOCAL"), in a container managed environment (transaction-type="JTA"), the transactions and entity manager life-cycle are managed by the container.


Acquiring an Entity Manager
There are two ways to acquire an entity manager; @PersistenceContext and JNDI look up.
Persistence Context is a set of managed entity instances at a given time (e.g., a Book with ID 34 and ...) which live for the duration of the transaction.


Persisting an Entity
It means inserting data into the database when data does not already exist (otherwise an exception is thrown).
void persist(Object entity); makes an instance managed and persistent (eligible to be persisted into database). Until the transaction is committed, the data stays in memory and there would be no access to database.


Finding an Entity by ID
<> T find(Class<> entityClass, Object primaryKey); searches for an entity of the specified class and primary key. If the entity is found, it is returned otherwise a null value is returned.

<> T getReference(Class<> entityClass, Object primaryKey); gets an instance whose state may be lazily fetched (a reference to the entity is retrieved and not its whole data). If the entity is not found, an "EntityNotFoundException" is thrown.


Removing an Entity
void remove(Object entity); removes the entity instance from the persistence context and from the underlying database.
By Orphan-Removal it is possible to inform the persistence provider to automatically remove orphans (rows that are not referenced without means of access) or cascade a remove operation. The OrphanRemoval option is provided in OneToOne and OneToMany associations.


Synchronizing with Database

  • Flushing Data to Database
    void flush(); synchronizes the persistence context to the underlying database.
    If the data is flushed at one point and if later in the application, the rollback() method is called, the flushed data will be taken out of the database.
    Before flushing, there must be a transaction started but flush() will not wait for transaction to commit.
    If the data integrity is violated, the transaction will rollback (IllegalStateException).
    Explicit flushes should be carefully used and only when needed.
    Note that by persisting an object (entity) through persist(), the object becomes managed and after this time you can call flush().

  • Refreshing an Entity from Database
    void refresh(Object entity); is used for data synchronization in the opposite direction of flush, overwriting changes made to the entity (if any). It is mostly used to undo the changes that have been done to the entity in memory only.


Other Important Methods of Entity Manager

  • void persist(Object entity);
    makes the instance managed by persistence provider (puts it into persistence context).

  • boolean contains(Object entity);
    checks if the instance is managed (in persistence context).

  • void clear();
    detaches all managed entities from context.

  • void detach(Object entity);
    detaches the entity from context

  • <> T merge(T entity);
    merges (attaches) the entity's state into persistence context.


Cascading Events
Propagating an operation (event) on an entity to its associations is called cascading events. The mechanism cascades the event to the target of the association. Possible events to be cascaded are; PERSIST, REMOVE, MERGE, REFRESH, DETACH or ALL(all the events).
Note that, cascading REMOVE may cause orphan entities in some implementations.


Cache API
Entity-Manager is the first level cache. It focuses on functional details and not the performance details. Second level cache (implemented by JPA implementations and not a specification) optimizes database access, queries, joins and so on for performance reasons by keeping objects loaded in memory and available to the whole application.
javax.persistence.Cache is the second level cache implemented by some persistence providers.


Mapping with XML
You can override the entity annotations (on a class) through specifying a file named '[entity-name]_mapping.xml' under META-INF folder and reference the file in persistence.xml by <> filename.xml < /mapping-file >. A sample descriptor file could contain something like the following;
< class = "...">
< name = "...">
<>
< name = "title">
< name = "..." nullable = "...">
< /basic >
< /attributes >
< /entity >


JPQL
The Java Persistence Query Language is used to query entities and work with objects and attributes instead of tables and columns while it does not see the underlying database structure nor deal with tables and columns.
SQL results are in rows and columns but JPQL results in an entity or a collection of entities.
JPQL example; SELECT b FROM Book b
Instead of selecting from a table, JPQL selects entities. Executing this statement results in a list of zero or many Book instances.
JPQL example; SELECT b FROM Book b WHERE b.title = "ABC"
Allowed statements in JPQL are; SELECT, UPDATE and DELETE.


SELECT
SELECT <>
FROM <>
[WHERE <>]
[ORDER BY <>]
[GROUP BY <>]
[HAVING <>]
SELECT clause can result in;

  • an entity or an entity attribute
  • a constructor expression
  • an aggregate function
  • or some sequence of above

Examples;
JPQL resulting in entity attribute;
SELECT c.firstName FROM Customer c
It returns a String or a collection of Strings.

SELECT c.firstName, c.lastName FROM Customer c
It returns a list, containing the two attributes.

SELECT c.address.country.code FROM Customer c
This is a chained navigating expression.

JPQL resulting in class instance;
SELECT NEW CustomerAD(c.firstName, c.lastName, c.address.street1) FROM Customer c
it returns the list of initialized CustomerAD objects. As you see, the constructor of the class is used in SELECT expression and the class doesn't need to be entity.

TO remove duplicates from the returning list use DISTINCT;
SELECT DISTINCT c.firstName FROM Customer c

JPQL resulting in aggregate function;
SELECT COUNT(c) FROM Customer c
Supported aggregate functions are; AVG, COUNT, MAX, MIN and SUM which may be grouped through GROUPED BY and filtered through HAVING.



FROM
It defines entities by declaring identification variables (alias).
FROM <> <>


WHERE
Example;
SELECT c
FROM Customer c
WHERE c.firstName = 'Youness' AND c.address = 'Persia'

Operators;
AND, OR
= , > , >= , < , <= , <>
[NOT] BETWEEN, [NOT] LIKE, [NOT] IN
IS [NOT] NULL, IS [NOT] EMPTY
[NOT] MEMBER [OF]

Examples;
LIKE '%flower.org' ('_' for single-character and '%' for multi-character representation)
BETWEEN 100 AND 200
IN('IRAN', 'GREECE')


Scalar Expressions
They can be used in SELECT, WHERE and HAVING clauses.
Numeric; ABS, SQRT, MOD, SIZE, INDEX
String; CONCAT, SUBSTRING, TRIM, LOWER, UPPER, LENGTH
Date/Time; CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP


Binding Parameters
Parameters can be bound (assigned to query dynamically) when query executes in two ways;

  • Positional parameters
    SELECT c
    FROM Customer c
    WHERE c.firstName = ?1 AND c.address.country = ?2
    (The integer identifiers after question marks must be in order.)

  • Named parameters
    SELECT c
    FROM Customer c
    WHERE C.firstName = :fname


Sub-queries
SELECT clause can be embedded in a WHERE or HAVING clause.
SELECT c
FROM Customer c
WHERE c.age = (SELECT MIN(c.age) FROM Customer c)


ORDER BY
SELECT c
FROM Customer c
WHERE c.age > 18
ORDER BY c.age DESC, c.address ASC
(Note; Ascending is the default ordering.)


GROUP BY & HAVING
SELECT c.address.country, count(c)
FROM Customer c
GROUP BY c.address.country
HAVING COUNT(c) > 100
(Note; Expression that appear in the GROUP BY clause must also appear in the SELECT clause. GROUP BY and HAVING can only appear with in a SELECT clause.)


DELETE
It is mostly useful in bulk delete in which we can remove a list of entities in a single operation instead of calling remove() on each entity. As a result, the number of entity instances affected by the operation is returned.

DELETE FROM [[AS] <>]
WHERE <>

example;
DELETE
FROM Customer c
WHERE c.age <>


UPDATE
Mostly useful for bulk updates;

UPDATE [[AS] <>]
SET <> {, <>}*
[WHERE <>]

example;
UPDATE Customer c
SET c.firstName = 'YOUNGSTER'
WHERE c.age <>


Queries

  • Dynamic Query; a JPQL is dynamically specified at run-time
  • Named Query; a static and unchangeable query
  • Native Query; native SQL statement (not JPQL)
  • Criteria API Query
Entity Manager has a set of methods to create a Query (dynamic, named, native).

Query interface has methods to;
  • execute a query and return a result; getResultList(), getSingleResult(), executeUpdate() (The latter method is mostly used for bulk update/delete)

  • set/get parameter to/from the query; setParameter(...), getNamedParameters(), getPositionalParameters()

  • constrain the number of results returned by query (useful to return the results in chunks and pagination); setMaxResults(int), getFirstResult(int) (Note that the integer parameter is zero index based. The method starts from record at int position until max result is read. Also note that nothing is returned by these two methods if the parameter is not set properly.)

  • set/get query hints

  • set/get flush-mode (mechanism to handle pending changes and queries; AUTO, COMMIT) and lock-mode type to be used for query execution; setFlushMode(FlushModeType), getFlushMode(), setLockMode(LockModeType), getLockMode()

    AUTO is the default flush mechanism in which the provider is responsible for ensuring pending changes are visible to the processing of the query.
    On the other hand, COMMIT is a mechanism in which changes are made if the affect of updates made to entities do not overlap with changed data in persistence context.

  • allow access to the provider specific API


Query Types

  • Dynamic Query;

    Query EntityManager.createQuery(String);

    The string parameter is a JPQL query.
    The statement can be dynamically created at runtime.
    Use Query.setParameter(...) to bind positional/named parameters.
    The result is not predictable since the provider has to parse the JPQL statement, get the ORM metadata, and generate the equivalent SQL.

  • Named Query;
    The definition is done through annotation like this;

    @Entity
    @NamedQueries({@NamedQuery(name="...", query="..."), ...})
    public class ...

    and it is created by EntityManager.createNamedQuery([name])
    The name of the query is scoped to persistence unit and must be unique.
    Dynamic parameters also can be applied to query part.

  • Native Query;
    Useful in using specific features of a database.
    Not expected to be portable across different databases but results in entities.
    The definition is done through annotation like the following;

    @NamedNativeQueries({...})

    Note that the name of the query must be unique within persistence unit.
    The creation is done through EntityManager.createNativeQuery(...)


Concurrency
  • Synchronization must be controlled using a locking mechanism.
    • Optimistic locking; allows concurrency to be as permissive as possible.
    • Pessimistic locking; a lock is obtained on a resource before operating on it.

  • Locking Mechanism Levels
    • Locking mechanism at Entity Manager level
      <> T find (class <>, Object, LockModeType); read and lock
      lock (Object, LockModeType); read then lock
      refresh (Object, LockModeType)
      In all above, Object is an entity in the context.

    • Locking mechanism at Query (JPQL) level
      Query setLockMode (LockModeType); sets LockModeType for query execution.

  • LockModeType
    • Optimistic types
      OPTIMISTIC
      OPTIMISTIC_FORCE_INCREMENT (Uses versioning mechanism discussed below.)

    • Pessimistic types
      PESSIMISTIC_READ
      There is no need to reread the data at the end of transaction to get lock. It helps to ensure that the data is not updated between successive reads. It does not block other transactions to read the data.

      PESSIMISTIC_WRITE
      Forces serialization among transactions attempting to update the entity. It locks the entity as soon as a transaction updates the entity. It is used when there is a high likelihood of update failure among concurrent updating transactions.

      PESSIMISTIC_FORCE_INCREMENT
      Uses versioning mechanism discussed below.

      The preceding three types are used to immediately obtain long term database locks.

    • NONE
      No locking mechanism is specified.


Versioning Entities
When you persist an entity for the first time into the database, it gets version number 1. Later if you update (an attribute on the) entity and commit this change to the database, the entity version will get number 2, and so on.
To make use of this mechanism, the entity must be annotated with @Version on a field of type int, Integer, short, Short, long, Long or timestamp. Such a field is mapped to the database to store the version number.
Only the provider (not the entity) is allowed to update/set the value of the version attribute.
The mechanism is useful when the entity is modified by more than one process/thread.
By applying the mechanism, the entity is automatically enabled for optimistic locking.


Optimistic Locking
The decision to acquire a lock on the entity is actually made at the end of transaction.
Violating transactions result in 'OptimisticLockException' and are marked to rollback.
Ways to through OptimisticLockException;

  • Explicitly locking the entity through lock() or find(...) methods using LockModeType. Note that the first method has read then lock and the second one, read and lock behavior.
  • Implicitly locking through which the provider checks the version attribute. The exception may be thrown at commit time or by calling flush() method in two different transactions.

When using Versioning, both OPTIMISTIC and OPTIMISTIC_FORCE_INCREMENT mechanisms perform a version check on locked entity before commitment and throw OptimisticLockException if entity version mismatches but only the OPTIMISTIC_FORCE_INCREMENT mechanism forces an increment on the version at the end of the transaction even if the entity is not modified.


Pessimistic Locking
A lock is obtained eagerly on entity before operating on it (low level mechanism).
Databae locks the row to prevent other threads operating on it.
Transactions that violate this constraint throw "PessimisticLockException" and are marked for rollback.
This mechanism is used in applications with higher risk.


Callback Methods
Life cycle callback methods and listeners are invoked for each instance of an entity in response to a certain event (before or after the event occurs).
Note, when a serialized managed entity crosses the network and is deserialized, it is seen as a detached object and must be merged to context.
Applicable annotations are; @PrePersist, @PostPersist, @PreUpdate, @PostUpdate, @PreRemove, @PostRemove, @PostLoad.
The following diagram is the entity life cycle with callback annotations;



As you see, the post-load is called when there is a call to the database to find the entity through ID or JPQL or to refresh it. As discussed before, also merging a detached entity causes a call to post-load annotated method.
The following notes are also important when working with callback methods;

  • Multiple annotations (of not the same type) can be applied to the same method in entity. Therefore, a method may be called multiple times.
  • Method must not be static or final.
  • Method must not throw checked exceptions.
  • Method cannot invoke any EntityManager or Query operations.
  • With inheritance the supper method annotated same as the child method is called first.
  • The callback methods get called in cascade way in relationships.


Entity Listeners
Entity listener classes are used to extract business logic to a separate class and share it between entities. Entity listener is a POJO containing one or more callback methods.
The entity can use @EntityListeners annotation to register itself to one or many listeners. When more than one entity listener is specified in the annotation, entity iterates through the list in order, passing its reference to each.
The EntityListener class must have;

  • a no argument, public constructor
  • the methods used to have access to the entity state
  • the method has a parameter which must be compatible with listener entities
  • same method rules as callback methods with one exception; In inhritance hierarchy, the supperclass listeners (if any) are invoked first. In this case, to avoid the supperclass listeners, use @ExcludeSupperclassListeners


Default Listeners
This kind of entity listeners are described in a separate xml file which must be referred in persistence.xml file. They are called by default before any listener declared in the entity and are overridden with @ExcludeDefaultListeners.







Last update 2011/2/24