EJB3 and JPA Basics



EJB3 and JPA Basics

Mapped Superclasses
A mapped superclass provides a convenient class on which to store shared state and behavior that entities can inherit from, but it is itself not a persistent class and cannot act in the capacity of an entity. It cannot be queried over and cannot be the target of a relationship. Annotations such as @Table are not permitted on mapped superclasses because the state defined in them applies only to its entity subclasses.
It is good practice to make mapped superclass as abstract Java classes.mapped superclasses do not get mapped to tables.
Entity Inheritance
The Java Persistence specification provides three different ways to map an inheritance hierarchy to a relational database:
A single table per class hierarchy
One table will have all properties of every class in the hierarchy.
A table per concrete class
Each class will have a table dedicated to it, with all of its properties and the properties of its superclass mapped to this table.
A table per subclass
Each class will have its own table. Each table will have only the properties that are defined in that particular class. These tables will not have properties of any superclass or subclass.
The root entity class defines the inheritance strategy with the @Inheritance annotation. Inheritance has only one property: InheritanceType strategy InheritanceType is an enum, which has value: SINGLE_TABLE, TABLE_PER_CLASS, JOINED. The default one is SINGLE_TABLE
Single-Table Strategy(A single table per class hierarchy)
This strategy maps all classes in the hierarchy to one table, which contains a superset of all the possible state in any of the entity classes.
@Entity
@Table(name="Employee")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="Employee_Type")
public abstract class Employee
@Entity
@DiscriminatorValue("Contract_Employee")
public class ContractEmployee
Discriminator Column and Discriminator Value
The table has to have one extra column to indicate the type.
Advantages

It offers peak performance for both polymorphic queries and write operations. The SQL that is needed to issue these operations is simple, optimized, and does not require joining.
Single table inheritance mapping is the fastest of all inheritance models, since it never requires a join to retrieve a persistent instance from the database. Similarly, persisting or updating a persistent instance requires only a single INSERT or UPDATE statement. Finally, relations to any class within a single table inheritance hierarchy are just as efficient as relations to a base class.
Disadvantages
Single-table approach tends to be more wasteful of database tablespace, as for every field in the entire inheritance hierarchy, a column must exist in the mapped table, as many columns may be empty.
Joined Strategy(A table per subclass)
The InheritanceType.JOINED strategy uses a different table for each class in the hierarchy. Each table only includes state declared in its class.
@Entity
@Table(name="Employee")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="Employee_Type")
public abstract class Employee
PrimaryKeyJoinColumn annotations tell the JPA implementation how to join each subclass table record to the corresponding record in its direct superclass table.
Advantages
The joined strategy has the following advantages:
Using joined subclass tables results in the most normalized database schema, meaning the schema with the least spurious or redundant data.
As more subclasses are added to the data model over time, the only schema modification that needs to be made is the addition of corresponding subclass tables in the database (rather than having to change the structure of existing tables).
Relations to a base class using this strategy can be loaded through standard joins and can use standard foreign keys, as opposed to the machinations required to load polymorphic relations to table-per-class base types, described below.
Disadvantages
Aside from certain uses of the table-per-class strategy described below, the joined strategy is often the slowest of the inheritance models. Retrieving any subclass requires one or more database joins, and storing subclasses requires multiple INSERT or UPDATE statements.
Table-per-Concrete-Class Strategy(A table per concrete class)
Like the JOINED strategy, the InheritanceType.TABLE_PER_CLASS strategy uses a different table for each concrete class in the hierarchy. Unlike the JOINED strategy, however, each table includes all state for an instance of the corresponding class. Thus to load a subclass instance, the JPA implementation must only read from the subclass table; it does not need to join to superclass tables.
Advantages
The table-per-class strategy is very efficient when operating on instances of a single concrete class. As in this case, the strategy never requires joining to superclass or subclass tables. Reads, joins, inserts, updates, and deletes are all efficient in the absence of polymorphic behavior. Also, as in the joined strategy, adding additional classes to the hierarchy does not require modifying existing class tables.
Disadvantages
The negative side is that it makes polymorphic querying across a class hierarchy more expensive than the other strategies. The problem is that it must either issue multiple separate queries across each of the subclass tables, or query across all of them using a UNION operation. This is always expensive.
Fetch Type
FetchType.EAGER or FetchType.LAZY
Cascade Type
public enum CascadeType {ALL,PERSIST,MERGE,REMOVE,REFRESH,DETACH}
Directionality
Unidirectional or bidirectional
Entitys Relationships
Many-to-one, One-to-one, One-to-many, Many-to-many
Persistence Context
A persistent context manages a set of managed entity object instances.
The entity manager tracks all entity objects within a persistence context for changes and updates made, and flushes these changes to the database.
As soon as an EntityManager object is created, it is implicitly associated with a persistence context for managing a set of entities.
Persistent Context comes in two flavors, one is the transaction-scoped persistent context and the other one is extended persistent context.
Transaction-Scoped Persistence Context
Life-time of transaction-scoped persistence context is dependent on the life-time of the transaction.
When the transaction completes, the transaction-scoped persistence context will be destroyed and all man-aged entity object instances will become detached.
Only persistence contexts managed by an application server may be transaction-scoped.
Extended Persistence Context
@PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;
Extended persistence context lives even after a transaction completes.
Entity object instances that are attached to an extended context remain managed even after a transaction is complete.
An EntityManager using an extended persistence context maintains the same persistence context for its entire lifecycle.
It is often used in stateful session beans.
Detached entities
Entity instances become unmanaged and detached when a transaction scope or extended persistence context ends. An interesting side effect is that detached entities can be serialized and sent across the network to a remote client. The client can make changes remotely to these serialized object instances and send them back to the server to be merged back and synchronized with the database.
merge()
The Java Persistence specification allows you to merge state changes made to a detached entity back into persistence storage using the entity manager’s merge() method.
If the entity manager isn’t already managing an instance, a full copy of the parameter is made and returned from the merge() method. This copy is managed by the entity manager, but the instance you pass in will not be managed.
Any additional setter methods called on this copy will be synchronized with the database when the EntityManager decides to flush.
The original parameter remains detached and unmanaged.
Either way will add an entity to a PersistenceContext, the difference is in what you do with the entity afterwards.
Persist takes an entity instance, adds it to the context and makes that instance managed (ie future updates to the entity will be tracked)
Merge creates a new instance of your entity, copies the state from the supplied entity, and makes the new copy managed. The instance you pass in will not be managed (any changes you make will not be part of the transaction - unless you call merge again).
The Stateful Session Bean
Stateful session beans maintain conversational state,
The Singleton Session Bean
@javax.ejb.Singleton
@javax.ejb.Startup
public class MySingletonBean implements MySingletonLocalBusiness{..}
Container Managed Transactions (CMT)
In a CMT the container starts, commits and rolls back a transaction on our behalf, we however must tell the container how to manage the transaction by using either deployment descriptors or annotations and ask it to rollback the transaction when needed.
@TransactionManagement(TransactionManagementType.CONTAINER|BEAN)
@TransactionAttribute
TransactionAttributes
REQUIRED  means the method must always be invoked in a transaction, either creating a new one or joining an existing one, this creates a single umbrella transaction.
REQUIRES_NEW    means that the method will always create a new transaction, if the client already has a transaction; it is temporary suspended until our method returns. The success of the newly created transaction has no affect on an existing transaction.
SUPPORTS  will inherit whatever transactional environment of the caller is, if it does not have one then no transaction is used, if it joins an already existing transaction it will not cause it to suspend
MANDATORY    means that a transaction must already exist if one does not then an EJBTransactionRequiredException error is thrown.
NOT_SUPPORTED   means that the method will not run in an transaction, if one already exists then this is suspended until the method completes then resumes. this is useful for an MDB supporting a JMS provider in a non-transactional, autoknowledge mode.
NEVER means that it cannot be invoked by a transactional client, otherwise a EJBException is thrown.
Transaction Attribute   
Type               Caller Transaction Exists    Effect
REQUIRED          No    Container creates a new transaction
                     Yes   Method joins the callers transaction
REQUIRES_NEW    No    Container creates a new transaction
                     Yes   Container creates a new transaction and the callers transaction is suspended
SUPPORTS          No    No transaction is used
                     Yes    Method joins the callers transaction
MANDATORY        No   javax.ejb.EJBTransactionRequiredException is thrown
                     Yes  Method joins the callers transaction
NOT_SUPPORTED   No   No transaction is used
                     Yes  The callers transaction is suspended and the method is called without a transaction
NEVER             No   No transaction is used
                     Yes   javax.ejb.EJBException is thrown
Bean-Managed Transactions
BMT allows you to specify exactly where the transaction starts, ends, commits and rolls back, using the javax.transaction.UserTransaction interface.
@TransactionManagement(TransactionManagementType.BEAN)
@Resource private UserTransaction userTransaction;
userTransaction.begin;
userTransaction.commit();
userTransaction.setRollbackOnly();
@ApplicationException(rollback=false|true)[TODO]
Applied to an exception to denote that it is an application exception and should be reported to the client directly (i.e., unwrapped).
@ApplicationException(rollback=false)
public class DatabaseException extends RuntimeException
Isolation and Database Locking
Dirty, Repeatable, and Phantom Reads
Dirty reads
A dirty read occurs when a transaction reads uncommitted changes made by a previous transaction. If the first transaction is rolled back, the data read by the second transaction becomes invalid because the rollback undoes the changes. The second transaction will not be aware that the data it has read has become invalid.
Repeatable reads
A repeatable read occurs when the data read is guaranteed to look the same if read again during the same transaction. Repeatable reads are guaranteed in one of two ways: either the data read is locked against changes, or it is a snapshot that doesn’t reflect changes.
If the data is locked, it cannot be changed by any other transaction until the current transaction ends. If the data is a snapshot, other transactions can change the data, but these changes will not be seen by this transaction if the read is repeated.
A nonrepeatable read occurs when the data retrieved in a subsequent read within the same transaction can return different results.
When a transaction queries for the same data twice in the same transaction, the second query returns a different version of the data than was returned the first time because another transaction modified it in the intervening time.
In other words, the subsequent read can see the changes made by other transactions.
Phantom reads
A phantom read occurs when new records added to the database are detectable by transactions that started prior to the insert. Queries will include records added by other transactions after their transaction has started.
Database Locks
The most common locks are read locks, write locks, and exclusive write locks.
Read locks
Read locks prevent other transactions from changing data read during a transaction until the transaction ends, thus preventing non-repeatable reads. Other transactions can read the data but not write to it. The current transaction is also prohibited from making changes.
Write locks
Write locks are used for updates. A write lock prevents other transactions from changing the data until the current transaction is complete but allows dirty reads by other transactions and by the current transaction itself. In other words, the transaction can read its own uncommitted changes.
Exclusive write locks
Exclusive write locks are used for updates. An exclusive write lock prevents other transactions from reading or changing the data until the current transaction is complete. It also prevents dirty reads by other transactions. Some databases do not allow transactions to read their own data while it is exclusively locked.
Snapshots
A snapshot is a frozen view of the data that is taken when a transaction begins.
Some databases get around locking by providing every transaction with its own snapshot. Snapshots can prevent dirty reads, nonrepeatable reads, and phantom reads. They can be problematic because the data is not real-time data; it is old the instant the snapshot is taken.
Transaction Isolation Levels
Read Uncommitted
The transaction can read uncommitted data (i.e., data changed by a different transaction that is still in progress). Dirty reads, nonrepeatable reads, and phantom reads can occur
Read Committed
The transaction cannot read uncommitted data; data that is being changed by a different transaction cannot be read. Dirty reads are prevented; nonrepeatable reads and phantom reads can occur.
Repeatable Read
The transaction cannot change data that is being read by a different transaction.
Dirty reads and non-repeatable reads are prevented; phantom reads can occur.
Serializable
The transaction has exclusive read and update privileges; different transactions can neither read nor write to the same data. Dirty reads, nonrepeatable reads, and phantom reads are prevented.
Optimistic Locking
Using optimistic locking, we assume there is a good chance that current transaction will be the only one that actually changes the entity during that interval.
So we don't acquire a lock on the entity until the change is actually made to the database, usually at the end of the transaction.
At transaction commit time, we let the database resolve whether the data has been altered by another transaction. If it has, we throw an exception and roll back our transaction. In other words, we are being optimistic that the data hasn’t been touched until we need to commit.
Versioning
To determine whether others have changed same data in the intervening time since the committing transaction read the entity, the provider maintains a versioning system for the entity, defines a version column to track the version of a row.
@Version private Long version;
A @Version property is a column that will hold a version ID of a particular row.
Whenever the entity class is updated, the version column is incremented automatically by JPA. When a transaction beginning the commit process and business logic has updated the entity, the entity manager first checks to see whether the version property of the in-memory entity instance matches the version column currently stored in the database. If the versions match, then the version property is incremented. If they don’t match, then the entity manager throws an exception(OptimisticLockException) and rolls back the whole transaction.
Advanced Optimistic Locking Modes
Optimistic Read Locking(LockModeType.OPTIMISTIC)
An optimistic read lock in JPA provides Repeatable Read.
The resulting lock will guarantee that both the transaction that obtains the entity read lock and any other that tries to change that entity instance will not both succeed.
Optimistic Write Locking(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
The write lock guarantees all that the optimistic read lock does, but also pledges to increment the version field in the transaction regardless of whether a user updated the entity or not. This provides a promise of an optimistic lock failure if another transaction also tries to modify the same entity before this one commits.
When not use optimistic lock?
The optimistic locking design pattern does not work all the time.
If you have a row in your database that has a high concurrent write contention, then it is probably less efficient to use the optimistic locking pattern because it will create a lot of rollbacks, which create a lot of overhead in your system.
Pessimistic Locking
Pessimistic locking implies obtaining a lock on one or more objects immediately.
It guarantees locked object will not be modified by another transaction until after the current transaction completes and releases its lock.
Disadvantages
This limits the scalability and concurrency of applications because needless locking serializes many operations that could easily occur in parallel.
Pessimistic Locking Modes
By far the most common is pessimistic write locking.
Pessimistic Write Locking(LockModeType.PESSIMISTIC_WRITE)
This mode will be translated by most providers into a SQL "SELECT FOR UPDATE" statement in the database, obtaining a write lock on the entity so no other applications can modify it.
Pessimistic Read Locking(LockModeType.PESSIMISTIC_READ)
A PESSIMISTIC_READ mode can be used to pessimistically achieve repeatable read semantics when no writes to the entity are expected.
Pessimistic Forced Increment Locking
(LockModeType.PESSIMISTIC_FORCE_INCREMENT)
This mode will also increment the version field of the locked entity regardless of whether changes were made to it.

@Basic
The @Basic annotation is the simplest form of mapping for a persistent property. This is the default mapping type for properties that are primitives, primitive wrapper types.
Lazy Loading
We declare fetch attribute to lazy on mapping relationship, such as @Basic, @OneToMany, @ManyToOne, @OneToOne, and @ManyToMany.
If the fetch() attribute is LAZY, that particular property will not be initialized
until you actually access this field.
Open Session in View
The problem
If your view (jsp) need access object's property that is lazy loaded, you will get exception:
LazyInitializationException: Session has been closed.
This is because the session has already been closed.
Using an interceptor|Filter to implement
sf.getCurrentSession().beginTransaction();
chain.doFilter(request, response);
sf.getCurrentSession().getTransaction().commit();
Solution for Hibernate
Spring provides OpenSessionInViewFilter.
Solution for JPA
In JPA, we can use extended entityManager(extended persistence context), or Spring's OpenEntityManagerInviewFilter.

Resources

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)