cmp2.x jdbc2 pm
This is a name of a default entity bean container configuration which uses CMP2.x compatible JDBC based persistence manager in the org.jboss.ejb.plugins.cmp.jdbc2 package. The development of this persistence manager was driven by performance tests.
The reasons to write a new persistence manager instead of optimizing the existing one were:
we needed a better performance which could not be achieved with the existing persistence manager which is quite sophisticated and performing major rafactorings is not easy w/o breaking the documented functionality and testsuites;
we needed to address major architectural issues in caching and locking;
we needed a more efficient persistent data synchronization mechanism.
Previously, you had to choose between a (cross-transactional) cache (i.e. commit option A) with pessimistic locking in EJB container and no cache with no locking in EJB container (e.g. Instance Per Transaction container configuration with no or optimistic locking). These are two extreme cases. The new persistence manager addresses this issue by using a two level cache.
Entity instance cache is a per transaction cache. (In fact, the implementation is one that is used in the Instance Per Transaction container configuration.) Plus, there is a global (cross-transaction) cache of row data (think of it like a cache of database rows).
It means that each transaction gets its own copy of the entity EJB instance (from the instance cache) associated with the same persistent data (in the row cache). Concurrent transactions can work on the same persistent data simulteniously. To prevent concurrent modifications leading to inconsistency in the database it is recommended to use optimistic locking.
Since each transaction gets its own copy of entity EJB instances, there is no need for pessimistic locking in the EJB container. But we use a global cache. And operations like put into, remove from the cache, etc require pessimistic locking on the cache level. It is still better than holding a pessimistic lock on the instance for the duration of the transaction though. Plus, there are configuration options to reduce lock contention on the cache.
Let's look at the default container-cache-conf element for this container:
<container-cache-conf> <cache-policy-conf> <min-capacity>500</min-capacity> <max-capacity>10000</max-capacity> <!-- time-based eviction <overager-period>300</overager-period> <max-bean-age>600</max-bean-age> --> </cache-policy-conf> <cache-policy-conf-other> <partitions>10</partitions> <!-- uncomment to use JDBC java.sql.Statement.executeBatch() <batch-commit-strategy></batch-commit-strategy> --> </cache-policy-conf-other> </container-cache-conf>
The initial capacity of the cache
The maximum capacity of the cache. max-capacity is used by the size-based eviction policy, i.e. if the maximum capacity is exceeded, the data is evicted with Least Recently Used policy.
These two settings if used must be used together. They define time-based eviction policy. Support for these options in 'cmp2.x jdbc2 pm' was added in jboss-3.2.8RC1 and jboss-4.0.4beta. The meaning of these options is exactly the same as in the traditional 'Standard CMP 2.x EntityBean'.
To reduce lock contention, the cache is devided into partitions. When we need to put or remove an instance from the cache we lock only the partition the instance belongs to, not the whole cache leaving other partitions available for concurrent transactions.
If present the synchronization will use java.sql.PreparedStatement.executeBatch().
Each row cache is an MBean.
With this persistence manager the synchronization occurs only at commit time and query execution except for findByPrimaryKey. When an instance is created the corresponding INSERT statement is issued also at commit time unless insert-after-ejb-post-create is true. In the former case INSERT statement will be issued right after ejbPostCreate callback on the instance.