diff --git a/reference/en/modules/collection_mapping.xml b/reference/en/modules/collection_mapping.xml index 9bbd780e76..e01cf34792 100644 --- a/reference/en/modules/collection_mapping.xml +++ b/reference/en/modules/collection_mapping.xml @@ -566,109 +566,6 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set - - Lazy Initialization - - - Collections (other than arrays) may be lazily initialized, meaning they load - their state from the database only when the application needs to access it. - Initialization of collections owned by persistent instances happens transparently - to the user, so the application would not normally need to worry about this (in - fact, transparent lazy initialization is the main reason why Hibernate needs its - own collection implementations). However, if the application tries something like - this: - - - - - - It could be in for a nasty surprise. Since the permissions collection was not - initialized when the Session was closed, the collection - will not be able to load its state. Hibernate does not support lazy - initialization for detached objects. The fix is to move the - line that reads from the collection to just before the commit. (There are - other more advanced ways to solve this problem, however.) - - - - It's possible to use a non-lazy collection. However, it is intended that lazy - initialization be used for almost all collections, especially for collections - of entities, and is now the default. If you define too many non-lazy associations - in your object model, Hibernate will end up needing to fetch the entire database - into memory in every transaction! - - - - Exceptions that occur while lazily initializing a collection are wrapped in a - LazyInitializationException. - - - - In some application architectures, particularly where the code that accesses data - using Hibernate, and the code that uses it are in different application layers, it - can be a problem to ensure that the Session is open when a - collection is initialized. They are two basic ways to deal with this issue: - - - - - - In a web-based application, a servlet filter can be used to close the - Session only at the very end of a user request, once - the rendering of the view is complete. Of course, this places heavy - demands upon the correctness of the exception handling of your application - infrastructure. It is vitally important that the Session - is closed and the transaction ended before returning to the user, even - when an exception occurs during rendering of the view. The servlet filter - has to be able to access the Session for this approach. - We recommend that a ThreadLocal variable be used to - hold the current Session (see chapter 1, - , for an example implementation). - - - - - In an application with a seperate business tier, the business logic must - "prepare" all collections that will be needed by the web tier before - returning. This means that the business tier should load all the data and - return all the data already initialized to the presentation/web tier that - is required for a particular use case. Usually, the application calls - Hibernate.initialize() for each collection that will - be needed in the web tier (this call must occur before the session is closed) - or retrieves the collection eagerly using a Hibernate query with a - FETCH clause. - - - - - You may also attach a previously loaded object to a new Session - with update() or lock() before - accessing unitialized collections (or other proxies). Hibernate can not - do this automatically, as it would introduce ad hoc transaction semantics! - - - - - - You can use a collection filter to get the size of a collection without initializing it: - - - - - - The createFilter() method is also used to efficiently retrieve subsets - of a collection without needing to initialize the whole collection. (And the new - <filter> functionality is a more powerful approach.) - - - - Sorted Collections diff --git a/reference/en/modules/configuration.xml b/reference/en/modules/configuration.xml index afce6ec061..7b59ec13be 100644 --- a/reference/en/modules/configuration.xml +++ b/reference/en/modules/configuration.xml @@ -876,7 +876,7 @@ hibernate.dialect = \ - + Outer Join Fetching @@ -888,30 +888,20 @@ hibernate.dialect = \ in a single SQL SELECT. - - By default, the fetched graph when loading an objects ends at leaf objects, - collections, objects with proxies, or where circularities occur in the case - of *-to-one associations. Hibernate will however execute an immediate additional - SELECT for any persistent collection (we recommend that you - turn on lazy loading for all collection mappings). - - - - For a particular association, fetching may be enabled - or disabled (and the default behaviour overridden) by setting the - outer-join attribute in the XML mapping. - - Outer join fetching may be disabled globally by setting the property hibernate.max_fetch_depth to 0. A setting of 1 or higher enables outer join fetching for - all one-to-one and many-to-one associations, which are, also by default, set - to auto outer join. However, one-to-many associations and - collections are never fetched with an outer-join, unless explicitly declared - for each particular association. This behavior can also be overriden at runtime - with Hibernate queries. See the query chapters in the documentation for more - details. + all one-to-one and many-to-one associations if no other fetching strategy is + defined in the mapping and if proxying of the target entity + class has been turned off (thus disabling lazy loading). However, one-to-many + associations and collections are never fetched with an outer-join, unless + explicitly declared for each particular association. This + behavior can also be overriden at runtime with Hibernate queries. + + + + See for more information. diff --git a/reference/en/modules/manipulating_data.xml b/reference/en/modules/manipulating_data.xml index 2643c36aeb..5b5806a99e 100644 --- a/reference/en/modules/manipulating_data.xml +++ b/reference/en/modules/manipulating_data.xml @@ -2,7 +2,7 @@ Working with Persistent Data - + Creating a persistent object @@ -24,6 +24,8 @@ Long generatedId = (Long) sess.save(fritz);]]> is called. If Cat has an assigned identifier, or a composite key, the identifier should be assigned to the cat instance before calling save(). + You may also use create() instead of save(), + with the semantics defined in the EJB3 early draft. @@ -105,14 +107,16 @@ return cat;]]> You may even load an object using an SQL SELECT ... FOR UPDATE. - See the next section for a discussion of Hibernate LockModes. + See the next sections for a discussion of Hibernate LockModes. Note that any associated instances or contained collections are - not selected FOR UPDATE. + not selected FOR UPDATE, unless you decide + to specify lock or all as a + cascade style for the association. @@ -125,6 +129,13 @@ return cat;]]> sess.flush(); //force the SQL INSERT sess.refresh(cat); //re-read the state (after the trigger executes)]]> + + An important question usually appears at this point: How much does Hibernate load + from the database and how many SQL SELECTs will it use? This + depends on the fetching strategy and is explained in + . + + diff --git a/reference/en/modules/performance.xml b/reference/en/modules/performance.xml index b75ca92fc2..8674311243 100644 --- a/reference/en/modules/performance.xml +++ b/reference/en/modules/performance.xml @@ -196,238 +196,487 @@ - - We have already shown how you can use lazy initialization for persistent collections - in the chapter about collection mappings. A similar effect is achievable for ordinary object - references, using CGLIB proxies. We have also mentioned how Hibernate caches persistent - objects at the level of a Session. More aggressive caching strategies - may be configured upon a class-by-class basis. - - - - In the next section, we show you how to use these features, which may be used to - achieve much higher performance, where necessary. - - - - Proxies for Lazy Initialization + + Fetching strategies - Hibernate implements lazy initializing proxies for persistent objects using runtime - bytecode enhancement (via the excellent CGLIB library). + A fetching strategy describes the number of instances, the depth of a + subgraph of instances, and SQL SELECTs that are used + to retrieve these instances. Hibernate supports several strategies and you + can configure them on a global level, per entity class, per association, or + even for a particular query in HQL and with Criteria. - The mapping file may declare an interface to use as the proxy interface for that - class. By default, Hibernate uses a subclass of the class itself. (The proxied - class must implement a default constructor with at least package visibility.) - - - - There are some gotchas to be aware of when extending this approach to polymorphic - classes, eg. + Hibernate offers the following fetching strategies: - - ...... - - ..... - -]]> - - - Firstly, instances of Cat will never be castable to - DomesticCat, even if the underlying instance is an - instance of DomesticCat. - - - - - - Secondly, it is possible to break proxy ==. - - - - - - However, the situation is not quite as bad as it looks. Even though we now have two references - to different proxy objects, the underlying instance will still be the same object: - - - - - - Third, you may not use a CGLIB proxy for a final class or a class - with any final methods. - - - - Finally, if your persistent object acquires any resources upon instantiation (eg. in - initializers or default constructor), then those resources will also be acquired by - the proxy. The proxy class is an actual subclass of the persistent class. - - - - These problems are all due to fundamental limitations in Java's single inheritence model. - If you wish to avoid these problems your persistent classes must each implement an interface - that declares its business methods. You should specify these interfaces in the mapping file. eg. - - - - ...... - - ..... - -]]> - - - where Cat implements the interface ICat and - DomesticCat implements the interface IDomesticCat. Then - proxies for instances of Cat and DomesticCat may be returned - by load() or iterate(). (Note that find() - does not usually return proxies.) - - - - - - Relationships are also lazily initialized. This means you must declare any properties to be of - type Cat, not CatImpl. - - - - Certain operations do not require proxy initialization - - - + - equals(), if the persistent class does not override - equals() + Lazy fetching - an associated instance (or a + collection) will only be loaded when needed, using an additional + defered SELECT. - hashCode(), if the persistent class does not override - hashCode() + Batch fetching - an optimization strategy + for lazy fetching, Hibernate not only retrieves a single instance + (or collection), but several in the same SELECT. - The identifier getter method + Eager fetching - Hibernate retrieves the + associated instance (or collection) in the same SELECT, + using an OUTER JOIN. + + + + + Select fetching - a second SELECT + is used to retrieve the associated instance (or collection), but + it might be executed immediately and not defered until first access + (as with lazy fetching). - + - Hibernate will detect persistent classes that override equals() or - hashCode(). + By default, Hibernate3 will only load the given entity using a single + SELECT statement if you retrieve an object with + load() or get(). This means that + all single-ended associations and collections are set for lazy fetching + by default. You can change this global default by setting the + default-lazy attribute on the hibernate-mapping + element to false. - Exceptions that occur while initializing a proxy are wrapped in a - LazyInitializationException. - - - - Sometimes we need to ensure that a proxy or collection is initialized before closing the - Session. Of course, we can alway force initialization by calling - cat.getSex() or cat.getKittens().size(), for example. - But that is confusing to readers of the code and is not convenient for generic code. - The static methods Hibernate.initialize() and Hibernate.isInitialized() - provide the application with a convenient way of working with lazyily initialized collections or - proxies. Hibernate.initialize(cat) will force the initialization of a proxy, - cat, as long as its Session is still open. - Hibernate.initialize( cat.getKittens() ) has a similar effect for the collection - of kittens. - - - - - - Using batch fetching - - - Hibernate can make efficient use of batch fetching, that is, Hibernate can load several uninitialized - proxies if one proxy is accessed. Batch fetching is an optimization for the lazy loading strategy. - There are two ways you can tune batch fetching: on the class and the collection level. + We'll now have a closer look at the individual fetching strategies and how + to change them for single-ended associations and collections. - - Batch fetching for classes/entities is easier to understand. Imagine you have the following situation - at runtime: You have 25 Cat instances loaded in a Session, each - Cat has a reference to its owner, a Person. - The Person class is mapped with a proxy, lazy="true". If you now - iterate through all cats and call getOwner() on each, Hibernate will by default - execute 25 SELECT statements, to retrieve the proxied owners. You can tune this - behavior by specifying a batch-size in the mapping of Person: - + + Collection fetching - ...]]> + + Initialization of collections owned by persistent instances happens transparently + to the user, so the application would not normally need to worry about this (in + fact, transparent lazy initialization is the main reason why Hibernate needs its + own collection implementations). However, if the application tries something like + this: + - - Hibernate will now execute only three queries, the pattern is 10, 10, 5. You can see that batch fetching - is a blind guess, as far as performance optimization goes, it depends on the number of unitilized proxies - in a particular Session. - + - You may also enable batch fetching of collections. For example, if each Person has - a lazy collection of Cats, and 10 persons are currently loaded in the - Sesssion, iterating through all persons will generate 10 SELECTs, - one for every call to getCats(). If you enable batch fetching for the - cats collection in the mapping of Person, Hibernate can pre-fetch - collections: - +Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]> - + + It could be in for a nasty surprise. Since the permissions collection was not + initialized when the Session was closed, the collection + will not be able to load its state. Hibernate does not support lazy + initialization for detached objects. The fix is to move the + line that reads from the collection to just before the commit. (There are + other more advanced ways to solve this problem, some are discussed later.) + + + + It's possible to use a non-lazy collection. However, it is intended that lazy + initialization be used for almost all collections, especially for collections + of entity references (its the default). If you define too many non-lazy associations + in your object model, Hibernate will end up needing to fetch the entire database + into memory in every transaction! Still, sometimes you want to use an additional + SELECT for a particular collection right away, not defered + until the first access happens: + + + + + + + + + Hibernate will now execute an immediate second SELECT loading + the collection of Permission instances, when a particular + User is retrieved. + + + + Any kind of lazy fetching (and also Select fetching) is extremely vulnerable to + N+1 selects problems. So usually, we choose lazy fetching only as a default + strategy, and override it for a particular transaction, using the HQL + LEFT JOIN FETCH clause. This tells Hibernate to fetch the + association eagerly in the first select, using an outer join. In the + Criteria API, you would use + setFetchMode(FetchMode.EAGER). + + + + You can always force outer join association fetching in the mapping file, by setting + fetch="join" (or use the old outer-join="true" + syntax). We don't recommend this setting, especially not for collections, since it is + incredibly rare to find an entity which is always used when + an associated entity is used, at least in a sufficiently large system. + + + + Eager fetching for collections has another restriction: you may only set one + collection role per persistent class to be fetched per outer join. Hibernate forbids + Cartesian products when possible, SELECTing two collections per + outer join would create one. This would almost always be slower than two (lazy or + non-defered) SELECTs. The restriction to a single outer-joined + collection applies to both the mapping fetching strategies and to HQL/Criteria queries. + + + + + + Single-ended association proxies + + + Lazy fetching for collections is implemented using Hibernate's own implementation + of persistent collections. However, a different mechanism is needed for lazy + behavior in single-ended associations. The target entity of the association must + be proxied. Hibernate implements lazy initializing proxies for persistent objects + using runtime bytecode enhancement (via the excellent CGLIB library). + + + + By default, Hibernate3 generates proxies (at startup) for all persistent classes + and uses them to enable lazy fetching of many-to-one and + one-to-one associations. + + + + The mapping file may declare an interface to use as the proxy interface for that + class, with the proxy attribute. By default, Hibernate uses a subclass + of the class. Note that the proxied class must implement a default constructor + with at least package visibility. We recommend this constructor for all persistent classes! + + + + There are some gotchas to be aware of when extending this approach to polymorphic + classes, eg. + + + + ...... + + ..... + + ]]> + + + Firstly, instances of Cat will never be castable to + DomesticCat, even if the underlying instance is an + instance of DomesticCat: + + + + + + Secondly, it is possible to break proxy ==. + + + + + + However, the situation is not quite as bad as it looks. Even though we now have two references + to different proxy objects, the underlying instance will still be the same object: + + + + + + Third, you may not use a CGLIB proxy for a final class or a class + with any final methods. + + + + Finally, if your persistent object acquires any resources upon instantiation (eg. in + initializers or default constructor), then those resources will also be acquired by + the proxy. The proxy class is an actual subclass of the persistent class. + + + + These problems are all due to fundamental limitations in Java's single inheritence model. + If you wish to avoid these problems your persistent classes must each implement an interface + that declares its business methods. You should specify these interfaces in the mapping file. eg. + + + + ...... + + ..... + + ]]> + + + where Cat implements the interface ICat and + DomesticCat implements the interface IDomesticCat. Then + proxies for instances of Cat and DomesticCat may be returned + by load() or iterate(). (Note that find() + does not usually return proxies.) + + + + + + Relationships are also lazily initialized. This means you must declare any properties to be of + type Cat, not CatImpl. + + + + Certain operations do not require proxy initialization + + + + + + equals(), if the persistent class does not override + equals() + + + + + hashCode(), if the persistent class does not override + hashCode() + + + + + The identifier getter method + + + + + + Hibernate will detect persistent classes that override equals() or + hashCode(). + + + + You may of course also use Eager or Select fetching strategies for single-ended + associations: + + + +]]> + + + The first mapping tells Hibernate to fetch the associated mother + entity in the same initial SELECT using an OUTER JOIN. + You can set this option on as many *-to-one associations as you like, there is no + danger of creating a Cartesian product (opposed to collections). Note that you can + set the maximum depth of outer joined tables with the global configuration option + max_fetch_depth (see ). + + + + The second mapping enables an additional SELECT for the + retrieval of the father. Note that Hibernate does not guarantee + when this query will be executed. If it should be executed + immediately (right after the initial SELECT), disable proxying + on the target of the association by setting it to lazy="false": + + + ...]]> + + + (Note that this example uses only a single persistent class Cat + and self-referencing associations. This doesn't change the fetching behavior, as expexted.) + + + + + + Initializing collections and proxies + + + An exception (LazyInitializationException) will be thrown by + Hibernate if an unitialized collection or proxy is accessed outside of the scope + of the Session, ie. when the entity owning the collection or + having the reference to the proxy is in detached state. + + + + Sometimes we need to ensure that a proxy or collection is initialized before closing the + Session. Of course, we can alway force initialization by calling + cat.getSex() or cat.getKittens().size(), for example. + But that is confusing to readers of the code and is not convenient for generic code. + + + + The static methods Hibernate.initialize() and Hibernate.isInitialized() + provide the application with a convenient way of working with lazyily initialized collections or + proxies. Hibernate.initialize(cat) will force the initialization of a proxy, + cat, as long as its Session is still open. + Hibernate.initialize( cat.getKittens() ) has a similar effect for the collection + of kittens. + + + + Another option is to keep the Session open until all needed + collections and proxies have been loaded. In some application architectures, + particularly where the code that accesses data using Hibernate, and the code that + uses it are in different application layers, it can be a problem to ensure that the + Session is open when a collection is initialized. There are + two basic ways to deal with this issue: + + + + + + In a web-based application, a servlet filter can be used to close the + Session only at the very end of a user request, once + the rendering of the view is complete (the Open Session in + View pattern). Of course, this places heavy + demands on the correctness of the exception handling of your application + infrastructure. It is vitally important that the Session + is closed and the transaction ended before returning to the user, even + when an exception occurs during rendering of the view. The servlet filter + has to be able to access the Session for this approach. + We recommend that a ThreadLocal variable be used to + hold the current Session (see chapter 1, + , for an example implementation). + + + + + In an application with a seperate business tier, the business logic must + "prepare" all collections that will be needed by the web tier before + returning. This means that the business tier should load all the data and + return all the data already initialized to the presentation/web tier that + is required for a particular use case. Usually, the application calls + Hibernate.initialize() for each collection that will + be needed in the web tier (this call must occur before the session is closed) + or retrieves the collection eagerly using a Hibernate query with a + FETCH clause or a FetchMode.JOIN in + Criteria. This is usually easier if you adopt the + Command pattern instead of a Session Facade. + + + + + You may also attach a previously loaded object to a new Session + with merge() or lock() before + accessing unitialized collections (or other proxies). Hibernate can not + do this automatically, as it would introduce ad hoc transaction semantics! + + + + + + Sometimes you don't want to initialize a large collection, but still need some + information about it (like its size) or a subset of the data. + + + + You can use a collection filter to get the size of a collection without initializing it: + + + + + + The createFilter() method is also used to efficiently retrieve subsets + of a collection without needing to initialize the whole collection: + + + + + + + + Using batch fetching + + + Hibernate can make efficient use of batch fetching, that is, Hibernate can load several uninitialized + proxies if one proxy is accessed (or collections. Batch fetching is an optimization for the lazy + loading strategy. There are two ways you can tune batch fetching: on the class and the collection level. + + + + Batch fetching for classes/entities is easier to understand. Imagine you have the following situation + at runtime: You have 25 Cat instances loaded in a Session, each + Cat has a reference to its owner, a Person. + The Person class is mapped with a proxy, lazy="true". If you now + iterate through all cats and call getOwner() on each, Hibernate will by default + execute 25 SELECT statements, to retrieve the proxied owners. You can tune this + behavior by specifying a batch-size in the mapping of Person: + + + ...]]> + + + Hibernate will now execute only three queries, the pattern is 10, 10, 5. You can see that batch fetching + is a blind guess, as far as performance optimization goes, it depends on the number of unitilized proxies + in a particular Session. + + + + You may also enable batch fetching of collections. For example, if each Person has + a lazy collection of Cats, and 10 persons are currently loaded in the + Sesssion, iterating through all persons will generate 10 SELECTs, + one for every call to getCats(). If you enable batch fetching for the + cats collection in the mapping of Person, Hibernate can pre-fetch + collections: + + + ... ]]> - - With a batch-size of 3, Hibernate will load 3, 3, 3, 1 collections in 4 - SELECTs. Again, the value of the attribute depends on the expected number of - uninitialized collections in a particular Session. - + + With a batch-size of 3, Hibernate will load 3, 3, 3, 1 collections in 4 + SELECTs. Again, the value of the attribute depends on the expected number of + uninitialized collections in a particular Session. + - - Batch fetching of collections is particularly useful if you have a nested tree of items, ie. - the typical bill-of-materials pattern. - + + Batch fetching of collections is particularly useful if you have a nested tree of items, ie. + the typical bill-of-materials pattern. (Although a nested set or a + materialized path might be a better option for read-mostly trees.) + - - - - Using lazy property fetching + - - Hibernate3 supports the lazy fetching of individual properties. This optimization technique - is also known as fetch groups. Please note that this is mostly a - marketing feature, as in practice, optimizing row reads is much more important than - optimization of column reads. However, only loading some properties of a class might - be useful in extreme cases, when legacy tables have hundreds of columns and the data model - can not be improved. - - - - To enable lazy property loading, set the lazy attribute on your - particular property mappings: - + + Using lazy property fetching - + + Hibernate3 supports the lazy fetching of individual properties. This optimization technique + is also known as fetch groups. Please note that this is mostly a + marketing feature, as in practice, optimizing row reads is much more important than + optimization of column reads. However, only loading some properties of a class might + be useful in extreme cases, when legacy tables have hundreds of columns and the data model + can not be improved. + + + + To enable lazy property loading, set the lazy attribute on your + particular property mappings: + + + @@ -436,17 +685,17 @@ Cat fritz = (Cat) iter.next();]]> ]]> - - Lazy property loading requires buildtime bytecode instrumentation! If your persistent - classes are not enhanced, Hibernate will silently ignore lazy property settings and - fall back to immediate fetching. - + + Lazy property loading requires buildtime bytecode instrumentation! If your persistent + classes are not enhanced, Hibernate will silently ignore lazy property settings and + fall back to immediate fetching. + - - For bytecode instrumentation, use the following Ant task: - + + For bytecode instrumentation, use the following Ant task: + - + @@ -460,42 +709,23 @@ Cat fritz = (Cat) iter.next();]]> ]]> - - A different (better?) way to avoid unnecessary column reads, at least for - read-only transactons is to use the projection features of HQL. This avoids - the need for buildtime bytecode processing. - + + A different (better?) way to avoid unnecessary column reads, at least for + read-only transactons is to use the projection features of HQL. This avoids + the need for buildtime bytecode processing. + + + + TODO: Document issues with lazy property loading + + + - TODO: Document issues with lazy property loading - - - - - - Outer join fetching - - - Any kind of lazy fetching is extremely vulnerable to N+1 selects problems. So usually, - we choose lazy fetching only as a "default" strategy, and override it for a particular - transaction, using the HQL LEFT JOIN FETCH clause. This tells Hibernate - to fetch the association in the first select, using an outer join. In the - Criteria API, you would use setFetchMode(FetchMode.EAGER). - - - - You can always force outer join association fetching in the mapping file, by setting - outer-join="true". We don't recommend this setting, especially - not for collections, since it is incredibly rare to find an entity which is - always used when an associated entity is used, at least in a - sufficiently large system. - - - - A completely different way to avoid problems with N+1 selects is to use the second-level + A completely different way to avoid problems with N+1 selects is to use the second-level cache. - + diff --git a/reference/en/modules/query_criteria.xml b/reference/en/modules/query_criteria.xml index 0fbd5adfcf..73fd911f0a 100644 --- a/reference/en/modules/query_criteria.xml +++ b/reference/en/modules/query_criteria.xml @@ -148,7 +148,7 @@ while ( iter.hasNext() ) { - + Dynamic association fetching @@ -164,7 +164,7 @@ while ( iter.hasNext() ) { This query will fetch both mate and kittens - by outer join. + by outer join. See for more information. diff --git a/reference/en/modules/query_hql.xml b/reference/en/modules/query_hql.xml index 491246be89..9b6c6f2d7d 100644 --- a/reference/en/modules/query_hql.xml +++ b/reference/en/modules/query_hql.xml @@ -72,7 +72,7 @@ - + Associations and joins @@ -123,12 +123,13 @@ from Formula form full join form.parameter param]]> - + In addition, a "fetch" join allows associations or collections of values to be initialized along with their parent objects, using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and - lazy declarations of the mapping file for associations and collections. + lazy declarations of the mapping file for associations and collections. See + for more information.