-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Proposal Loader redesign
Loader is an internal contract. The basic idea is that it builds SQL, prepares the Statement and processes the resulting ResultSet. To do that it follows the common legacy Hibernate pattern of class hierarchies; so there is a specific Loader impl for loading from a HQL query or batch loading or native-sql query or ... Al in all pretty inflexible.
What I envision here instead is Loader as a basic "coordination contract" which takes a ResultSet and a LoadPlan and knows how to process the ResultSet in terms of said LoadPlan. Currently LoadPlan does not exist, although to a degree it is a function of the current contract between the base Loader class and its subclasses. That just needs to be cleaned up and formalized.
The reasoning here is that this would allow better reuse of instances. LoadPlans could be built:
- statically from result-set-mapings, HQL specifications, etc
- dynamically based on fetch profiles etc
Also the LoadPlan would remain the same whether we are batching or not, how many ResultSets we are processing (think chained ResultSets or procedure cursor output params)
An optional goal is to help OGM reuse as much of the generic code as possible. Today OgmLoader
is a copy paste from the Hibernate ORM code later adapted to use the NoSQL GridDialect. This goal is not a must have of the Loader redesign but rather a nice to have.
List of things to consider in implementing:
- scrollable results + collection fetching should cause fetching to be done subsequently (subselect, etc). That is to allow unification of the concepts of (a) load a row, (b) load a row sequentially and (c) load a row sequentially n reverse. However, scrollable results + collection fetching + locking could be problematic
- paging + collection fetching should automatically cause fetching to be done subsequently (subselect, etc). This allows the paging numbers to refer to the number of results ultimately returned to the user rather than the number of SQL results, which is a more natural expectation
- better overall handling for follow-on locking
- I really like the idea of org.hibernate.loader.spi.AbstractResultProcessor.SubSelectFetchHandler for handling "follow on" stuff. The general idea is a delegate which exposes 2 callbacks: one called as we process each row, and a second called after we are all done. This pattern fits for both subselect fetching and follow-on locking. For that to work fully, would need to expand the current API there a bit to allow correlation during first callback between entity/collection and its corresponding return/fetch.
- Part of the process here is replacing the JoinWalkers with a true "visitor" approach. A potential improvement building off of that in terms of start up performance would be to simultaneously perform the multiple walkings of an entity tree in the same call (by passing multiple visitation strategies). If workable, could be a big perf win.
See https://hibernate.onjira.com/browse/HHH-7841 and related Jiras.
Initial proof-of-concept work is housed at https://github.com/sebersole/hibernate-loader-redesign. However, work has now moved beyond that initial proposal. In fact this proposal has really become a few distinct proposals:
- As discussed above, part of the design here is to replace JoinWalkers, which are responsible for walking the associations (joins) starting from an entity or collection persister. They are a delegate used by the Loader to generate SQL and to collect information about visited persisters and associations to process the eventual ResultSet. This has spawned a new proposal for better encapsulation of persister-level metadata.
- This better encapsulation of persister-level metadata is used to build LoadPlans. LoadPlans generically describe persister references and returns/fetches.
- SQL Generation - function of LoadPlan. This is still the original SQL Generation proposal, but the idea would be to consider LoadPlans in that design.