Professional Documents
Culture Documents
Hibernate Basics: Hello World Again
Hibernate Basics: Hello World Again
Hibernate Basics
Hello World again
02/23/07
Hello World I
Hello World II
Hello World IV
Hello World V
select m.MESSAGE_TEXT from MESSAGES m where m.MESSAGE_ID = 1 update MESSAGES set MESSAGE_TEXT = Greetings Earthling'
Notice that we did not explicitly call any update() method - automatic dirty checking gives us more flexibility when organizing data access code!
Professional Open Source
JBoss, Inc. 2003, 2004.
Hello World VI
02/23/07
Metadata options
The most popular and primary method is XML mapping files. Many Hibernate users have good experience with XDoclet. EJB3/Hibernate3 annotations are currently available in beta only, but this is expected to be stable very soon.
<hibernate-mapping" schema="AUCTION"> <class name="User" table="USERS" <id>...</id> <property name="login" column="LOGIN"/> <set name="items" ... </class> </hibernate-mapping>
Advantages
wide adoption and documentation availability clear separation from Java source
Disadvantages
difficult in refactoring needs special XML editor for auto-completion
10
XDoclet annotations
/** * @hibernate.class * table="CATEGORY" */ public class Category { /** * @hibernate.property */ public String getName() { return name; } ...
Advantages
Refactoring is easy Runs on all JDK versions
Disadvantages
not type-safe and auto-completion only available in IDEs Needs pre-processing step at build-time The XDoclet project is not making much progress
Professional Open Source
JBoss, Inc. 2003, 2004.
11
import javax.persistence.*; @Entity(access = AccessType.FIELD) public class User { @Id(generate = GeneratorType.AUTO) Long id; String loginName; @OneToMany(cascade = CascadeType.PERSIST) @JoinColumn(name = "USER_ID") Set<Item> items = new HashSet<Item>();
Advantages
Refactoring is easy Externalization of physical (or all) annotations to XML files Type-safe and no pre-processing required
Disadvantages
Needs JDK 5.0
Professional Open Source
JBoss, Inc. 2003, 2004.
12
Category
0..* 0..* 0..*
http://caveatemptor.hibernate.org
Item
0..* sells
CreditCard
JBoss, Inc. 2003, 2004.
BankAccount
Professional Open Source
13
User
homeAddress
Address
14
Mapping entities
<hibernate-mapping package="org.hibernate.auction.model" default-cascade="save-update" default-access="field" default-lazy="false"> <class name="User" table="USER" dynamic-insert="true" dynamic-update="true" persister="MyLDAPPersister"> <id>...</id> </class>
...
15
For new systems, we recommend the use of surrogate keys if no good natural candidate keys can be found - this strategy makes schema evolution simpler.
Professional Open Source
JBoss, Inc. 2003, 2004.
16
17
Identity mapping
<class name="Category" table="CATEGORY"> <id name="id" column="CATEGORY_ID" type="long"> <generator class="native"/> </id> ... </class>
18
19
1..*
User
default
BillingDetails
CreditCard
BankAccount
20
<class name="BillingDetails" abstract="true"> <property name="owner" column="OWNER"/> ... <union-subclass name="CreditCard" table="CREDIT_CARD> <property name="type" column="CREDIT_CARD_TYPE"/> ... </union-subclass> ... </class>
polymorphic queries result in a UNION instead of several selects many-valued assocations to superclass result in a UNION but have to be bidirectional (inverse="true") single-valued associations to superclass are still problematic, no foreign key constraint can be created
Professional Open Source
JBoss, Inc. 2003, 2004.
21
note the type discriminator column best performance, polymorphic queries and associations subclass columns must be nullable! we use the Hibernate <subclass> mapping
22
<class name="BillingDetails" table="BILLING_DETAILS"> <id name="id" column="BILLING_DETAILS_ID"> <generator class="native"/> </id> <discriminator column="BILLING_TYPE type=string/> <property name="name" column="OWNER"/> ... <subclass name="CreditCard" discriminator-value="CC"> <property name="type" column="CREDIT_CARD_TYPE"/> ... </subclass> ... </class>
23
<class name="BillingDetails" table="BILLING_DETAILS"> <id name="id" column="BILLING_DETAILS_ID"> <generator class="native"/> </id> <discriminator type=string formula=case when CREDIT_CARD_TYPE is null then BA else CC end/> <property name="name" column="OWNER"/> ... <subclass name="CreditCard" discriminator-value="CC"> <property name="type" column="CREDIT_CARD_TYPE"/> ... </subclass> ... </class>
If there is no discriminator column, we can use a SQL expression These can be very complicated if you like!
Professional Open Source
JBoss, Inc. 2003, 2004.
24
25
normalized model polymorphic associations even to particular subclasses we use the Hibernate <joined-subclass> mapping
Professional Open Source
JBoss, Inc. 2003, 2004.
26
<class name="BillingDetails" table="BILLING_DETAILS"> <id name="id" column="BILLING_DETAILS_ID"> <generator class="native"/> </id> <property name="name" column="OWNER"/> ... <joined-subclass name="CreditCard"> <key column="CREDIT_CARD_ID"/> <property name="type" column="CREDIT_CARD_TYPE"/> ... </joined-subclass> ... </class>
difficult to implement by hand, performance of outer joins is an issue ad hoc reporting might be more complex
27
02/23/07
28
new
Transient
garbage collection delete()
Persistent
evict() close()* clear()* update() saveOrUpdate() lock() merge()
garbage collection
Detached
* affects all instances in a Session
29
Transient instances
have no database state or database identity made persistent with save() or persist()
Persistent instances
have assigned database identity are managed and transactional, dirty checked by Hibernate made transient with delete() made detached with close() or evict() are reloaded with refresh()
Detached instances
have database identity but are not associated with a Session made persistent with update(), saveOrUpdate(), or merge()
30
Saving an object
User user = new User(); user.getName().setFirstName("John"); user.getName().setLastName("Doe"); Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Long newId = session.save(user); // session.save(user, new Long(1234) ); tx.commit(); session.close();
The state of user is detached, after the Session has been closed.
Professional Open Source
JBoss, Inc. 2003, 2004.
31
Loading an object
Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Object usr = session.get(User.class, 1234); //Object usr = session.load(User.class, 1234); tx.commit(); session.close();
The get() method returns null if the object can't be found, the load() throws an exception. The exception might also be thrown on first access of a proxy.
Professional Open Source
JBoss, Inc. 2003, 2004.
32
Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); Object a = session.load(Item.class, new Long(1234) ); Object b = session.load(Item.class, new Long(1234) ); if ( a == b ) System.out.println("a and b are identical"); tx.commit(); session.close();
33
Session session1 = HibernateUtil.getSession(); Transaction tx1 = session.beginTransaction(); Object itemA = session1.load(Item.class, new Long(1234) ); tx1.commit(); session1.close(); Session session2 = HibernateUtil.getSession(); Transaction tx2 = session.beginTransaction(); Object itemB = session2.load(Item.class, new Long(1234) ); tx2.commit(); session2.close(); Set allObjects = new HashSet(); allObjects.add(itemA); allObjects.add(itemB); System.out.println(allObjects.size()); // How many?
We have to implement equals() & hashCode() for classes. Don't use the identifer, but a business key.
Professional Open Source
JBoss, Inc. 2003, 2004.
34
// "usr" has been loaded in a previous Session usr.setPassword("secret"); Session sessionTwo = HibernateUtil.getSession(); Transaction tx = sessionTwo.beginTransaction(); sessionTwo.update(usr); usr.setLoginName("jonny"); tx.commit(); sessionTwo.close();
Hibernate can automatically check versions for optimistic concurrency control (more later).
Professional Open Source
JBoss, Inc. 2003, 2004.
35
Hibernate can automatically detect if an object is new (transient) and what is old (detached):
Session session = HibernateUtil.getSession() Transaction tx = session.beginTransaction(); session.saveOrUpdate(newOrOld); tx.commit(); session.close();
Hibernate by default instantiates a fresh object and compares it to the given instance. You can customize this behavior in your mapping files or with a custom routine using interception.
Professional Open Source
JBoss, Inc. 2003, 2004.
36
Transitive persistence
Instead of working with only single objects, Hibernate can cascade state changes to associated entity instances. Cascade attributes can be set individually for each association:
<many-to-one name="category" cascade="none"/> <set name="items" cascade="persist, merge, save-update">... <set name="children" cascade="all, orphan-delete">...
Available cascade options: persist, merge, save-update, delete, lock, refresh, evict, replicate, orphan-delete, all
Professional Open Source
JBoss, Inc. 2003, 2004.
37
Reattachment throws an exception if the "same" instance is already persistent in the Session. We have to merge the changes:
// "c" is detached and has Id "1234" c.setPassword("secret"); Session sessionTwo = HibernateUtil.getSession(); Transaction tx = sessionTwo.beginTransaction(); User a = (User) session.load(User.class, "1234"); User b = (user) session.merge(c); (a == b) // true (a == c) // false (b == c) // false a.getPassword() // secret b.getPassword() // secret tx.commit(); sessionTwo.close();
Professional Open Source
JBoss, Inc. 2003, 2004.
38
Summary
Hibernate's native methods offer saving of transient and reattachment of detached instances. EJB3 adds an alternative saving operation and the ability to merge detached object state into persistent state. Objects outside of the scope of identity have to implement equals() and hashCode() correctly if they are compared. A business key is the prefered way, since database identifiers may change during save. All state management operations can be cascaded to associated objects, saving API calls. Cascading options can be declared finegrained in mapping metadata.
39
02/23/07
40
Hibernate
Session Transaction Query Connection Pool
41
42
The XML-based configuration is almost equivalent to the properties, it has some more features (cache tuning). The XML file overrides the hibernate.properties options. We usually prefer the XML configuration file, especially in managed environments.
43
Managed environments
Hibernate
Session Transaction Query Resource Manager Transaction Manager
44
<hibernate-configuration> <session-factory name="java:hibernate/SessionFactory"> <property name="show_sql">true</property> <property name="connection.datasource"> java:/comp/env/jdbc/HelloDB </property> <property name="transaction.factory_class"> org.hibernate.transaction.CMTTransactionFactory </property> <property name="transaction.manager_lookup_class"> org.hibernate.transaction.JBossTransactionManagerLookup </property> <property name="dialect"> org.hibernate.dialect.PostgreSQLDialect </property> <mapping resource="hello/Message.hbm.xml"/> </session-factory> </hibernate-configuration>
Professional Open Source
JBoss, Inc. 2003, 2004.
45
Hibernate comes with a standard JMX MBean (org.hibernate.jmx.HibernateService) that is usable in any MBeanServer. Advantages
Defines a standard way to configure/manage Hibernate (although descriptors vary between MBeanServer implementations) Allows runtime configuration changes through the MBeanServers administration interface Exposes the SessionFactory through JNDI after MBean start for application usage
Disadvantages
JMX does not define a standard MBean lifecycle the MBean must be manually started after deployment the MBean must be manually stopped on undeployment
46
JBoss Application Server has a microkernel - all services are registered as JMX MBeans. The org.jboss.hibernate package defines a number of services to integrate Hibernate into JBoss AS Advantages:
Automatic startup and shutdown (no more static HibernateUtil) SessionFactory available via JNDI after MBean deployment Special packaging format (HAR) makes bundling/deploying even easier No need to specify mappings; they are discovered Integration with other JBoss services
Disadvantages:
HAR format and service descriptor (hibernate-service.xml) are proprietary to JBoss AS
Professional Open Source
JBoss, Inc. 2003, 2004.
47
HAR archives
48
caveatemptor-app.har ehcache.jar \---META-INF hibernate-service.xml \---org \---hibernate \---auction +---facade \---model Item.class Item.hbm.xml ...
The required JARs for Hibernate are picked up from ${server}/deploy/jboss-hibernate.deployer directory.
49
<?xml version="1.0"?> <server> <mbean code="org.jboss.hibernate.jmx.Hibernate" name="jboss.har:service=MyHibernateFactory"> <depends>jboss:service=Naming</depends> <depends>jboss:service=TransactionManager</depends> <depends>jboss.jca:service=LocalTxCM,name=PostgresDS</depends> <attribute name=SessionFactoryName">java:/hibernate/MySF</attribute> <attribute name="DatasourceName">java:/PostgresDS</attribute> <attribute name="Dialect">org.hibernate.dialect.PostgreSQLDialect</attribute> <attribute name="CacheProviderClass"> org.hibernate.cache.TreeCacheProvider </attribute> </mbean> </server>
50
51