- •Preface
- •1.1. Part 1 - The first Hibernate Application
- •1.1.1. Setup
- •1.1.2. The first class
- •1.1.3. The mapping file
- •1.1.4. Hibernate configuration
- •1.1.5. Building with Maven
- •1.1.6. Startup and helpers
- •1.1.7. Loading and storing objects
- •1.2. Part 2 - Mapping associations
- •1.2.1. Mapping the Person class
- •1.2.2. A unidirectional Set-based association
- •1.2.3. Working the association
- •1.2.4. Collection of values
- •1.2.5. Bi-directional associations
- •1.2.6. Working bi-directional links
- •1.3. Part 3 - The EventManager web application
- •1.3.1. Writing the basic servlet
- •1.3.2. Processing and rendering
- •1.3.3. Deploying and testing
- •1.4. Summary
- •2.1. Overview
- •2.1.1. Minimal architecture
- •2.1.2. Comprehensive architecture
- •2.1.3. Basic APIs
- •2.2. JMX Integration
- •2.3. Contextual sessions
- •3.1. Programmatic configuration
- •3.2. Obtaining a SessionFactory
- •3.3. JDBC connections
- •3.4. Optional configuration properties
- •3.4.1. SQL Dialects
- •3.4.2. Outer Join Fetching
- •3.4.3. Binary Streams
- •3.4.4. Second-level and query cache
- •3.4.5. Query Language Substitution
- •3.4.6. Hibernate statistics
- •3.5. Logging
- •3.6. Implementing a NamingStrategy
- •3.7. Implementing a PersisterClassProvider
- •3.8. XML configuration file
- •3.9. Java EE Application Server integration
- •3.9.1. Transaction strategy configuration
- •3.9.2. JNDI-bound SessionFactory
- •3.9.3. Current Session context management with JTA
- •3.9.4. JMX deployment
- •4.1. A simple POJO example
- •4.1.1. Implement a no-argument constructor
- •4.1.2. Provide an identifier property
- •4.1.3. Prefer non-final classes (semi-optional)
- •4.2. Implementing inheritance
- •4.3. Implementing equals() and hashCode()
- •4.4. Dynamic models
- •4.5. Tuplizers
- •4.6. EntityNameResolvers
- •5.1. Mapping declaration
- •5.1.1. Entity
- •5.1.2. Identifiers
- •5.1.2.1. Composite identifier
- •5.1.2.1.1. id as a property using a component type
- •5.1.2.1.2. Multiple id properties without identifier type
- •5.1.2.1.3. Multiple id properties with with a dedicated identifier type
- •5.1.2.2. Identifier generator
- •5.1.2.2.1. Various additional generators
- •5.1.2.2.2. Hi/lo algorithm
- •5.1.2.2.3. UUID algorithm
- •5.1.2.2.4. Identity columns and sequences
- •5.1.2.2.5. Assigned identifiers
- •5.1.2.2.6. Primary keys assigned by triggers
- •5.1.2.2.7. Identity copy (foreign generator)
- •5.1.2.3. Enhanced identifier generators
- •5.1.2.3.1. Identifier generator optimization
- •5.1.2.4. Partial identifier generation
- •5.1.3. Optimistic locking properties (optional)
- •5.1.3.1. Version number
- •5.1.3.2. Timestamp
- •5.1.4. Property
- •5.1.4.1. Property mapping with annotations
- •5.1.4.1.1. Type
- •5.1.4.1.2. Access type
- •5.1.4.1.3. Optimistic lock
- •5.1.4.1.4. Declaring column attributes
- •5.1.4.1.5. Formula
- •5.1.4.1.6. Non-annotated property defaults
- •5.1.4.2. Property mapping with hbm.xml
- •5.1.5. Embedded objects (aka components)
- •5.1.6. Inheritance strategy
- •5.1.6.1. Single table per class hierarchy strategy
- •5.1.6.1.1. Discriminator
- •5.1.6.2. Joined subclass strategy
- •5.1.6.3. Table per class strategy
- •5.1.6.4. Inherit properties from superclasses
- •5.1.6.5. Mapping one entity to several tables
- •5.1.7. Mapping one to one and one to many associations
- •5.1.7.1. Using a foreign key or an association table
- •5.1.7.2. Sharing the primary key with the associated entity
- •5.1.8. Natural-id
- •5.1.10. Properties
- •5.1.11.1. Doctype
- •5.1.11.1.1. EntityResolver
- •5.1.11. Some hbm.xml specificities
- •5.1.11.2. Hibernate-mapping
- •5.1.11.4. Import
- •5.1.11.5. Column and formula elements
- •5.2. Hibernate types
- •5.2.1. Entities and values
- •5.2.2. Basic value types
- •5.2.3. Custom value types
- •5.3. Mapping a class more than once
- •5.4. SQL quoted identifiers
- •5.5. Generated properties
- •5.6. Column transformers: read and write expressions
- •5.7. Auxiliary database objects
- •6.1. Value types
- •6.1.1. Basic value types
- •6.1.1.1. java.lang.String
- •6.1.1.2. java.lang.Character (or char primitive)
- •6.1.1.3. java.lang.Boolean (or boolean primitive)
- •6.1.1.4. java.lang.Byte (or byte primitive)
- •6.1.1.5. java.lang.Short (or short primitive)
- •6.1.1.6. java.lang.Integer (or int primitive)
- •6.1.1.7. java.lang.Long (or long primitive)
- •6.1.1.8. java.lang.Float (or float primitive)
- •6.1.1.9. java.lang.Double (or double primitive)
- •6.1.1.10. java.math.BigInteger
- •6.1.1.11. java.math.BigDecimal
- •6.1.1.12. java.util.Date or java.sql.Timestamp
- •6.1.1.13. java.sql.Time
- •6.1.1.14. java.sql.Date
- •6.1.1.15. java.util.Calendar
- •6.1.1.16. java.util.Currency
- •6.1.1.17. java.util.Locale
- •6.1.1.18. java.util.TimeZone
- •6.1.1.19. java.net.URL
- •6.1.1.20. java.lang.Class
- •6.1.1.21. java.sql.Blob
- •6.1.1.22. java.sql.Clob
- •6.1.1.23. byte[]
- •6.1.1.24. Byte[]
- •6.1.1.25. char[]
- •6.1.1.26. Character[]
- •6.1.1.27. java.util.UUID
- •6.1.1.28. java.io.Serializable
- •6.1.2. Composite types
- •6.1.3. Collection types
- •6.2. Entity types
- •6.3. Significance of type categories
- •6.4. Custom types
- •6.4.1. Custom types using org.hibernate.type.Type
- •6.4.2. Custom types using org.hibernate.usertype.UserType
- •6.4.3. Custom types using org.hibernate.usertype.CompositeUserType
- •6.5. Type registry
- •7.1. Persistent collections
- •7.2. How to map collections
- •7.2.1. Collection foreign keys
- •7.2.2. Indexed collections
- •7.2.2.1. Lists
- •7.2.2.2. Maps
- •7.2.3. Collections of basic types and embeddable objects
- •7.3. Advanced collection mappings
- •7.3.1. Sorted collections
- •7.3.2. Bidirectional associations
- •7.3.3. Bidirectional associations with indexed collections
- •7.3.4. Ternary associations
- •7.3.5. Using an <idbag>
- •7.4. Collection examples
- •8.1. Introduction
- •8.2. Unidirectional associations
- •8.2.1. Many-to-one
- •8.2.3. One-to-many
- •8.3. Unidirectional associations with join tables
- •8.3.1. One-to-many
- •8.3.2. Many-to-one
- •8.3.4. Many-to-many
- •8.4. Bidirectional associations
- •8.4.1. one-to-many / many-to-one
- •8.5. Bidirectional associations with join tables
- •8.5.1. one-to-many / many-to-one
- •8.5.3. Many-to-many
- •8.6. More complex association mappings
- •9.1. Dependent objects
- •9.2. Collections of dependent objects
- •9.3. Components as Map indices
- •9.4. Components as composite identifiers
- •9.5. Dynamic components
- •10.1. The three strategies
- •10.1.1. Table per class hierarchy
- •10.1.2. Table per subclass
- •10.1.3. Table per subclass: using a discriminator
- •10.1.4. Mixing table per class hierarchy with table per subclass
- •10.1.5. Table per concrete class
- •10.1.6. Table per concrete class using implicit polymorphism
- •10.2. Limitations
- •11.1. Hibernate object states
- •11.2. Making objects persistent
- •11.3. Loading an object
- •11.4. Querying
- •11.4.1. Executing queries
- •11.4.1.1. Iterating results
- •11.4.1.2. Queries that return tuples
- •11.4.1.3. Scalar results
- •11.4.1.4. Bind parameters
- •11.4.1.5. Pagination
- •11.4.1.6. Scrollable iteration
- •11.4.1.7. Externalizing named queries
- •11.4.2. Filtering collections
- •11.4.3. Criteria queries
- •11.4.4. Queries in native SQL
- •11.5. Modifying persistent objects
- •11.6. Modifying detached objects
- •11.7. Automatic state detection
- •11.8. Deleting persistent objects
- •11.9. Replicating object between two different datastores
- •11.10. Flushing the Session
- •11.11. Transitive persistence
- •11.12. Using metadata
- •12.1. Making persistent entities read-only
- •12.1.1. Entities of immutable classes
- •12.1.2. Loading persistent entities as read-only
- •12.1.3. Loading read-only entities from an HQL query/criteria
- •12.1.4. Making a persistent entity read-only
- •12.2. Read-only affect on property type
- •12.2.1. Simple properties
- •12.2.2. Unidirectional associations
- •12.2.2.1. Unidirectional one-to-one and many-to-one
- •12.2.2.2. Unidirectional one-to-many and many-to-many
- •12.2.3. Bidirectional associations
- •12.2.3.1. Bidirectional one-to-one
- •12.2.3.2. Bidirectional one-to-many/many-to-one
- •12.2.3.3. Bidirectional many-to-many
- •13.1. Session and transaction scopes
- •13.1.1. Unit of work
- •13.1.2. Long conversations
- •13.1.3. Considering object identity
- •13.1.4. Common issues
- •13.2. Database transaction demarcation
- •13.2.1. Non-managed environment
- •13.2.2. Using JTA
- •13.2.3. Exception handling
- •13.2.4. Transaction timeout
- •13.3. Optimistic concurrency control
- •13.3.1. Application version checking
- •13.3.2. Extended session and automatic versioning
- •13.3.3. Detached objects and automatic versioning
- •13.3.4. Customizing automatic versioning
- •13.4. Pessimistic locking
- •13.5. Connection release modes
- •14.1. Interceptors
- •14.2. Event system
- •14.3. Hibernate declarative security
- •15.1. Batch inserts
- •15.2. Batch updates
- •15.3. The StatelessSession interface
- •15.4. DML-style operations
- •16.1. Case Sensitivity
- •16.2. The from clause
- •16.3. Associations and joins
- •16.4. Forms of join syntax
- •16.5. Referring to identifier property
- •16.6. The select clause
- •16.7. Aggregate functions
- •16.8. Polymorphic queries
- •16.9. The where clause
- •16.10. Expressions
- •16.11. The order by clause
- •16.12. The group by clause
- •16.13. Subqueries
- •16.14. HQL examples
- •16.15. Bulk update and delete
- •16.16. Tips & Tricks
- •16.17. Components
- •16.18. Row value constructor syntax
- •17.1. Creating a Criteria instance
- •17.2. Narrowing the result set
- •17.3. Ordering the results
- •17.4. Associations
- •17.5. Dynamic association fetching
- •17.6. Example queries
- •17.7. Projections, aggregation and grouping
- •17.8. Detached queries and subqueries
- •17.9. Queries by natural identifier
- •18.1. Using a SQLQuery
- •18.1.1. Scalar queries
- •18.1.2. Entity queries
- •18.1.3. Handling associations and collections
- •18.1.4. Returning multiple entities
- •18.1.4.1. Alias and property references
- •18.1.5. Returning non-managed entities
- •18.1.6. Handling inheritance
- •18.1.7. Parameters
- •18.2. Named SQL queries
- •18.2.2. Using stored procedures for querying
- •18.2.2.1. Rules/limitations for using stored procedures
- •18.3. Custom SQL for create, update and delete
- •18.4. Custom SQL for loading
- •19.1. Hibernate filters
- •20.1. Working with XML data
- •20.1.1. Specifying XML and class mapping together
- •20.1.2. Specifying only an XML mapping
- •20.2. XML mapping metadata
- •20.3. Manipulating XML data
- •21.1. Fetching strategies
- •21.1.1. Working with lazy associations
- •21.1.2. Tuning fetch strategies
- •21.1.3. Single-ended association proxies
- •21.1.4. Initializing collections and proxies
- •21.1.5. Using batch fetching
- •21.1.6. Using subselect fetching
- •21.1.7. Fetch profiles
- •21.1.8. Using lazy property fetching
- •21.2. The Second Level Cache
- •21.2.1. Cache mappings
- •21.2.2. Strategy: read only
- •21.2.3. Strategy: read/write
- •21.2.4. Strategy: nonstrict read/write
- •21.2.5. Strategy: transactional
- •21.2.6. Cache-provider/concurrency-strategy compatibility
- •21.3. Managing the caches
- •21.4. The Query Cache
- •21.4.1. Enabling query caching
- •21.4.2. Query cache regions
- •21.5. Understanding Collection performance
- •21.5.1. Taxonomy
- •21.5.2. Lists, maps, idbags and sets are the most efficient collections to update
- •21.5.3. Bags and lists are the most efficient inverse collections
- •21.5.4. One shot delete
- •21.6. Monitoring performance
- •21.6.1. Monitoring a SessionFactory
- •21.6.2. Metrics
- •22.1. Automatic schema generation
- •22.1.1. Customizing the schema
- •22.1.2. Running the tool
- •22.1.3. Properties
- •22.1.4. Using Ant
- •22.1.5. Incremental schema updates
- •22.1.6. Using Ant for incremental schema updates
- •22.1.7. Schema validation
- •22.1.8. Using Ant for schema validation
- •23.1. Bean Validation
- •23.1.1. Adding Bean Validation
- •23.1.2. Configuration
- •23.1.3. Catching violations
- •23.1.4. Database schema
- •23.2. Hibernate Search
- •23.2.1. Description
- •23.2.2. Integration with Hibernate Annotations
- •24.1. A note about collections
- •24.2. Bidirectional one-to-many
- •24.3. Cascading life cycle
- •24.4. Cascades and unsaved-value
- •24.5. Conclusion
- •25.1. Persistent Classes
- •25.2. Hibernate Mappings
- •25.3. Hibernate Code
- •26.1. Employer/Employee
- •26.2. Author/Work
- •26.3. Customer/Order/Product
- •26.4. Miscellaneous example mappings
- •26.4.1. "Typed" one-to-one association
- •26.4.2. Composite key example
- •26.4.3. Many-to-many with shared composite key attribute
- •26.4.4. Content based discrimination
- •26.4.5. Associations on alternate keys
- •28.1. Portability Basics
- •28.2. Dialect
- •28.3. Dialect resolution
- •28.4. Identifier generation
- •28.5. Database functions
- •28.6. Type mappings
- •References
Chapter 7. Collection mapping
</bag> </class>
<class name="Item">
<id name="id" column="ITEM_ID"/>
...
<!-- inverse end -->
<bag name="categories" table="CATEGORY_ITEM" inverse="true">
<key column="ITEM_ID"/>
<many-to-many class="Category" column="CATEGORY_ID"/>
</bag> </class>
Changes made only to the inverse end of the association are not persisted. This means that Hibernate has two representations in memory for every bidirectional association: one link from A to B and another link from B to A. This is easier to understand if you think about the Java object model and how a many-to-many relationship in Javais created:
Example 7.28. Effect of inverse vs. non-inverse side of many to many
associations
category.getItems().add(item); |
// The |
category |
now "knows" |
about |
the relationship |
||
item.getCategories().add(category); |
// The |
item now |
"knows" about the |
relationship |
|||
session.persist(item); |
// |
The |
relationship |
won't be saved! |
|||
session.persist(category); |
// |
The |
relationship |
will be |
saved |
|
|
|
|
|
|
|
|
|
|
The non-inverse side is used to save the in-memory representation to the database.
7.3.3. Bidirectional associations with indexed collections
There are some additional considerations for bidirectional mappings with indexed collections (where one end is represented as a <list> or <map>) when using Hibernate mapping files. If there is a property of the child class that maps to the index column you can use inverse="true" on the collection mapping:
Example 7.29. Bidirectional association with indexed collection
<class name="Parent">
<id name="id" column="parent_id"/>
....
<map name="children" inverse="true">
<key column="parent_id"/> <map-key column="name"
type="string"/>
<one-to-many class="Child"/> </map>
</class>
176
Ternary associations
<class name="Child">
<id name="id" column="child_id"/>
....
<property name="name" not-null="true"/>
<many-to-one name="parent"
class="Parent"
column="parent_id" not-null="true"/>
</class>
If there is no such property on the child class, the association cannot be considered truly bidirectional. That is, there is information available at one end of the association that is not available at the other end. In this case, you cannot map the collection inverse="true". Instead, you could use the following mapping:
Example 7.30. Bidirectional association with indexed collection, but no
index column
<class name="Parent">
<id name="id" column="parent_id"/>
....
<map name="children">
<key column="parent_id" not-null="true"/> <map-key column="name" type="string"/>
<one-to-many class="Child"/> </map>
</class>
<class name="Child">
<id name="id" column="child_id"/>
....
<many-to-one name="parent"
class="Parent"
column="parent_id"
insert="false"
update="false"
not-null="true"/>
</class>
Note that in this mapping, the collection-valued end of the association is responsible for updates
to the foreign key.
7.3.4. Ternary associations
There are three possible approaches to mapping a ternary association. One approach is to use a Map with an association as its index:
177
Chapter 7. Collection mapping
Example 7.31. Ternary association mapping
@Entity
public class Company { @Id
int id;
...
@OneToMany // unidirectional @MapKeyJoinColumn(name="employee_id") Map<Employee, Contract> contracts;
}
// or
<map name="contracts">
<key column="employer_id" not-null="true"/> <map-key-many-to-many column="employee_id" class="Employee"/> <one-to-many class="Contract"/>
</map>
A second approach is to remodel the association as an entity class. This is the most common approach. A final alternative is to use composite elements, which will be discussed later.
7.3.5. Using an <idbag>
The majority of the many-to-many associations and collections of values shown previously all map to tables with composite keys, even though it has been suggested that entities should have synthetic identifiers (surrogate keys). A pure association table does not seem to benefit much from a surrogate key, although a collection of composite values might. For this reason Hibernate provides a feature that allows you to map many-to-many associations and collections of values to a table with a surrogate key.
The <idbag> element lets you map a List (or Collection) with bag semantics. For example:
<idbag name="lovers" table="LOVERS"> <collection-id column="ID" type="long">
<generator class="sequence"/>
</collection-id>
<key column="PERSON1"/>
<many-to-many column="PERSON2" class="Person" fetch="join"/> </idbag>
An <idbag> has a synthetic id generator, just like an entity class. A different surrogate key is assigned to each collection row. Hibernate does not, however, provide any mechanism for discovering the surrogate key value of a particular row.
The update performance of an <idbag> supersedes a regular <bag>. Hibernate can locate individual rows efficiently and update or delete them individually, similar to a list, map or set.
178
