-
Advantages:
- Fast performance
- Database Independent query
- Automatic table creation
- Simplifies complex join
- Provides query statistics and database status
-
Disadvantages:
- Mapping is relatively slow operation
- May not compatible with new version of database. Need to re-factor to newer version when updating database, which is painful.
- Hard for performance tuning because it doesn't have specific control of the underline SQL query.
Session Factory Connection Provider (optional)
|open |
Persistent | |
Object | begin |JNDI
App --------------> Session ---> Transaction -> JDBC -> Database
| JTA
Transaction Provider (optional)
- A factory of session
- A client of
ConnectionProvider
- Holds second level cache
- A short-lived object that wraps the JDBC connection.
- Provides interface between app and database
- A factory of
Transaction
,Query
,Criteria
. - Holds first-level cache (mandatory)
- Atomic unit of work
- A factory of JDBC connections.
- A factory of Transaction.
hiberate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="configurations">value</property>
<mapping resource="class_name.hbm.xml" />
</session-factory>
</hibernate-configuration>
-
Default model.
-
Also named: entity.
- A no-arg constructor with at least package visibility. (reflection.newInstance)
- An identifier property
- Prefer non-final class. (proxy pattern: lazy loading) (semi-optional)
- Declare getter and setter methods (optional)
- Implementing
equals()
andhashCode()
: make sure both of them guarantee that same row of database is mapping to the same object. (note: don't use identifier value)
class_name.hbm.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Class" table="table_name">
<id name="id_field" column="column_name"></id>
<property name="field" column="column_name"></property>
</hibernate-mapping>
Note: table, column can be omitted if class name is same as table name, field name is same as column name.
Try to reuse existing object in the session, in order to reduce the number of connection with database and improve performance.
- Each bean must has an ID for caching.
Note: each level of Caching can only store objects with unique ID.
Caching on Session: cache within current session.
- Enable by default.
- Each object has three status in a session:
- Transient:
- instantiate using
new
- no persistent representation in the database and no identifier value has been assigned.
- will be destroyed by GC.
- Persistent:
- has persistent representation in the database and an identifier value.
- final state will be synchronized with database when the unit of work completes.
- Detached:
- Was persistent, but the session is closed.
- can reattached to a new session, and all its modification will be persistent again.
A a = new A(); // Transient (map doesn't has a's id)
map.put(id, a) // Persistent
map.put(id, null) // Detached (map still has a's id)
map.put(id, a) // Persistent
load(a):
if map.contains(id):
return map.get(id)
else:
return map.put(id, a)
session.contains(objects)
: determines if an instance belongs to the session cache.session.evict(object)
: changes the object from persistent to detached.session.clear()
: evicts all objects.session.merge(object)
: changes the object from detached to persistent of current session.- Change non-id fields of persistent object, database will be updated after the transaction.
- Change id of persistent object, database will insert an new record with that id after the transaction.
Caching on SessionFactory: shallow copies will be shared across different sessions (entire application).
- Need to be enabled explicitly.
- Strategies:
- read-only: caching will work for read only operation.
- nonstrict-read-write: caching will work for read and write but one at a time.
- read-write: caching will work for read and write, can be used simultaneously.
- transactional: caching will work for transaction.
sessionFactory.evict(.class, id)
evict a particular object of class with id.sessionFactory.evict(.class)
evict all objects of class.sessionFactory.evictCollection(.class[, id])
collection version of evict.
-
Define CacheProvider in hibernate.cfg.xml
<!-- set to true by default --> <property name="cache.use_second_level_cache"> true </property> <property name="cache.provider_class"> EH Cache, Swarm, OS, JBoss </property>
Provider | read-only | nonstrict-read-write | read-write | transactional |
---|---|---|---|---|
Hashtable | Y | Y | Y | N |
EH Cache | Y | Y | Y | Y |
Swarm Cache | Y | Y | N | N |
OS Cache | Y | Y | Y | N |
JBoss Cache | Y | N | N | Y |
-
Add cache usage to hbm file
<class> <cache usage="read-only"/> ... </class>
-
Configure Cache Provider
- EhCache
<!-- ehcache.xml --> <?xml version="1.0"?> <ehcache> <defaultCache maxElementsInMemory="100" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="200" /> <cache name="bean_name" maxElementsInMemory="100" eternal="false" timeToIdleSeconds="5" timeToLiveSeconds="200" /> </ehcache>
Cache query result sets for queries with same parameters.
- query cache should always be used in conjunction with the second-level cache because it caches only identifier values and results of value type.
By default, both the entire query cache and the cache for individual query are disabled, because most of queries do not benefit from it.
<!-- enable query cache -->
<!-- hibernate.cfg.xml -->
<property name="cache.use_query_cache">true</property>
// enable query cache for a query
Query.setCacheable(true)
- Check whether this object is cached in the Session.
- Check whether this object is cached in the SessionFactory.
- Run a query to obtain that object.
- SQL:
SELECT s.name FROM Sample s WHERE s.age > 30;
| | | |
column table alias column
- HQL:
SELECT u.name FROM User as u where u.age > 30;
| | | |
field class obj field
-note: HQL does not support '*', we use 'from User' directly.
note: The translation of HQL is independent with mapping configuration.
- if we use object as the key (which is a must for composite key), then for
load()
, it will return an new object as the result, in contrast,get()
will fill in the object and return it.
class:
- assigned (default): assigned by user
- increment: max(id)+1
- sequence
- foreign
- native
- hilo
class Node<E> {
E value;
Node<E> parent;
Set<Node<E>> children;
}
By default, Hibernate will only load current object without loading any of its dependent objects (parent, children) unless we access them.
- Lazy Fetching can be disable by setting
lazy="false"
for its dependent sets. - Lazy Fetching dependent objects can be forced to initialize by calling
Hibernate.initialize(object)
.
Note: Lazy Fetching is different from Lazy Loading. Lazy Loading will not load current object until we access it.
A: Atomicity -
C: Consistency -
I: Isolation -
D: Durability -
-
Read uncommitted (no lock) - may cause dirty read (read dirty data)
-
Read committed (prevent dirty read) (default level) - affected rows are locked
-
Repeatable Read (prevent non-repeatable read)
-
Serializable (prevent phantom read)
- dirty read: T2 update, T1 read before T2 commit. Because reading is faster than update, at some point, T1 will start reading non-updated data.
Optimistic locking: no lock, but we can add an indicator column (such as version), then we can use it to control reading without a lock.
Details error message:
org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]
Hibernate needs a dependency javassist
which is not specified in its module. Therefore, we need to add it into maven
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>