[hibernate-dev] org.hibernate.persister.spi.PersisterFactory and 5.0

Gunnar Morling gunnar at hibernate.org
Tue Dec 2 03:15:38 EST 2014


2014-12-01 21:22 GMT+01:00 Steve Ebersole <steve at hibernate.org>:

> Wanted to point out that I carried those signatures on to the persister
> ctors as well.
>

Thx.

In Amsterdam we had talked about OGM needing a bootstrap hook for the point
> just after all persisters have been built.  Exactly what information did
> that hook need access to?
>

We'd need access to all the entity and collection persisters. For each
property which represents the main side of a bi-directional association, we
want to determine the persister on the other side, so we can fetch some
OGM-specific metadata from it.

In a local prototype, I added a parameterless method
doDeferredPostInstantiate() to OgmEntityPersister which I invoke by means
of an observer. From there I obtain the other persisters through the SF.

On Mon, Dec 1, 2014 at 11:28 AM, Steve Ebersole <steve at hibernate.org> wrote:
>
>> As for the "parameter object", I came up with a decent (imo) solution.
>> So I only wrap the things that are "contextual".  Here is the contract
>> right now:
>>
>>
>> public interface PersisterFactory extends Service {
>> /**
>>  * "Parameter object" providing access to additional information that may
>> be needed
>>  * in the creation of the persisters.
>>  */
>> public static interface PersisterCreationContext {
>> SessionFactoryImplementor getSessionFactory();
>> Metadata getMetadata();
>> }
>>
>> /**
>>  * Create an entity persister instance.
>>  *
>>  * @param entityBinding The mapping information describing the entity
>>  * @param entityCacheAccessStrategy The cache access strategy for the
>> entity region
>>  * @param naturalIdCacheAccessStrategy The cache access strategy for the
>> entity's natural-id cross-ref region
>>  * @param creationContext Access to additional information needed to
>> create an EntityPersister
>>  *
>>  * @return An appropriate entity persister instance.
>>  *
>>  * @throws HibernateException Indicates a problem building the persister.
>>  */
>> public EntityPersister createEntityPersister(
>> PersistentClass entityBinding,
>> EntityRegionAccessStrategy entityCacheAccessStrategy,
>> NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy,
>> PersisterCreationContext creationContext) throws HibernateException;
>>
>> /**
>>  * Create a collection persister instance.
>>  *
>>  * @param collectionBinding The mapping information describing the
>> collection
>>  * @param cacheAccessStrategy The cache access strategy for the
>> collection region
>>  * @param creationContext Access to additional information needed to
>> create an EntityPersister
>>  *
>>  * @return An appropriate collection persister instance.
>>  *
>>  * @throws HibernateException Indicates a problem building the persister.
>>  */
>> public CollectionPersister createCollectionPersister(
>> Collection collectionBinding,
>> CollectionRegionAccessStrategy cacheAccessStrategy,
>> PersisterCreationContext creationContext) throws HibernateException;
>>
>> }
>>
>> PersisterCreationContext is the contextual info.  And it can be
>> "statically" defined for each and every call into PersisterFactory.  The
>> other params to #createEntityPersister and #createCollectionPersister are
>> specific to that call.
>>
>>
>> On Thu, Nov 27, 2014 at 10:35 AM, Steve Ebersole <steve at hibernate.org>
>> wrote:
>>
>>> Actually, I take that back about Metadata extending org.hibernate.cfg.Mappings.
>>> I had contemplated doing that, but decided against it since Mappings
>>> exposes all kinds of "extra" stuff that isn't actually mappings/metadata
>>> (config info, contextual info, etc) and I did not want to fuglify these new
>>> contracts that way.
>>>
>>> On Thu, Nov 27, 2014 at 10:25 AM, Steve Ebersole <steve at hibernate.org>
>>> wrote:
>>>
>>>> Well naturally there is still access to all this information :)
>>>>
>>>> IMO SessionFactoryObserver is a hack way of doing this.  With 5.0, the
>>>> way to do this would be one of the various bootstrap hooks I mentioned
>>>> earlier.  Specifically you want a hook that is called just after all
>>>> metadata is fully known.
>>>>
>>>> BTW, for 5.0 the "metadata" is still using the mappings as defined in
>>>> the org.hibernate.mapping package.  So all that code fragment will continue
>>>> to work aside from actually using the Configuration.  Interestingly,
>>>> had you used org.hibernate.cfg.Mappings#iterateTables rather than
>>>> Configuration#getTableMappings(), this code would have continued to
>>>> work with no changes at all.  This is the point I made in the initial email
>>>> about Metadata also being a org.hibernate.cfg.Mappings.
>>>>
>>>>
>>>> On Thu, Nov 27, 2014 at 4:36 AM, Emmanuel Bernard <
>>>> emmanuel at hibernate.org> wrote:
>>>>
>>>>> To add on Gunnar’s needs
>>>>>
>>>>> 3. Use Configuration to extract physical Table structure
>>>>>
>>>>> We also use configuration in the SchemaDefiner
>>>>> The SchemaDefiner received the Configuration from a custom
>>>>> implementation of SessionFactoryObserver and use it during
>>>>> sessionFactoryCreated.
>>>>>
>>>>> The reason we use Configuration is so that this SchemaDefiner contract
>>>>> can:
>>>>>
>>>>> - access to specific properties (say hibernate.0gm.neo4j.index
>>>>> create-drop )
>>>>> - get information about the table, it’s unique constraints as shown in
>>>>> this pseudo example
>>>>>
>>>>> Iterator<Table> tableMappings = configuration.getTableMappings();
>>>>> while ( tableMappings.hasNext() ) {
>>>>>    Table table = tableMappings.next();
>>>>>    if ( table.isPhysicalTable() ) {
>>>>>       Label label = label( table.getName() );
>>>>>       PrimaryKey primaryKey = table.getPrimaryKey();
>>>>>       createConstraint( neo4jDb, table, label, primaryKey );
>>>>>       @SuppressWarnings("unchecked")
>>>>>       Iterator<Column> columnIterator = table.getColumnIterator();
>>>>>       while ( columnIterator.hasNext() ) {
>>>>>          Column column = columnIterator.next();
>>>>>          if ( column.isUnique() ) {
>>>>>             createUniqueConstraintIfMissing( neo4jDb, label,
>>>>> column.getName() );
>>>>>          }
>>>>>       }
>>>>>       Iterator<UniqueKey> uniqueKeyIterator =
>>>>> table.getUniqueKeyIterator();
>>>>>       while ( uniqueKeyIterator.hasNext() ) {
>>>>>          createConstraint( neo4jDb, table, label,
>>>>> uniqueKeyIterator.next() );
>>>>>       }
>>>>>    }
>>>>> }
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 27 Nov 2014, at 10:13, Gunnar Morling <gunnar at hibernate.org> wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> 2014-11-27 1:23 GMT+01:00 Steve Ebersole <steve at hibernate.org>:
>>>>>
>>>>> Part of the goals for ORM 5.0 is moving from Configuration to the
>>>>> ServiceRegistry+Metadata for building a SessionFactory.
>>>>>
>>>>> One of the points I ran into that will have to change
>>>>> is org.hibernate.persister.spi.PersisterFactory.  The problems is that
>>>>> PersisterFactory accepts a Configuration as part of building
>>>>> CollectionPersisters.  The need for Configuration in the standard
>>>>> CollectionPersister impls is amazingly trivial; we literally use it to
>>>>> locate the associated entity's PersistentClass to grab the classes
>>>>> dom4j
>>>>> node name, and this is right after we have just resolved the
>>>>> corresponding
>>>>> EntityPersister.  The point being that the standard
>>>>> CollectionPersisters
>>>>> really don't need access to the Configuration.
>>>>>
>>>>> I am pretty sure OGM provides a custom PersisterFactory, or is it just
>>>>> the PersisterClassResolver that OGM provides?  Also, I would assume
>>>>> OGM is
>>>>> providing custom CollectionPersister impls.  This change would affect
>>>>> both
>>>>> usages.
>>>>>
>>>>>
>>>>> We don't have a custom PersisterFactory, but there are
>>>>> OgmPersisterClassResolver [1] and OgmCollectionPersister [2]. In the
>>>>> latter
>>>>> we accept a Configuration in the constructor but just pass it to the
>>>>> super
>>>>> 'ctor (AbstractCollectionPersister). We don't do anything ourselves
>>>>> with it.
>>>>>
>>>>>
>>>>> I wanted y'all to be aware of this upcoming change.  But I also wanted
>>>>> to
>>>>> start a discussion about what the signature(s) should become.
>>>>> Currently we
>>>>> pass:
>>>>>
>>>>> * Configuration
>>>>> * Collection (the parsed mapping info)
>>>>> * CollectionRegionAccessStrategy
>>>>> * SessionFactoryImplementor
>>>>>
>>>>>
>>>>> I suggest we pass:
>>>>>
>>>>> * Collection
>>>>> * CollectionRegionAccessStrategy
>>>>> * SessionFactoryImplementor
>>>>> * Mapping
>>>>>
>>>>>
>>>>> Should be fine for OGM. I suggest to wrap it into a parameter object
>>>>> ("PersisterInitializationContext" or so). That way stuff can be added
>>>>> down
>>>>> the road without the need to instantly adapt existing persisters.
>>>>>
>>>>> (I changed order to align with the order for building EntityPersisters)
>>>>>
>>>>>
>>>>> Mapping is org.hibernate.engine.spi.Mapping which is part of
>>>>> Configuration.  I decided to (at least temporarily) port this contract
>>>>> forward to ease migration.  Metadata implements it.
>>>>>
>>>>> There is a similar discussion to be had wrt Integrators.  I will
>>>>> follow up
>>>>> with an email specific to them later.
>>>>>
>>>>>
>>>>> Regarding the removal of Configuration in general, there will be some
>>>>> more
>>>>> work to be done in OGM. We have a custom sub-class, OgmConfiguration
>>>>> [3],
>>>>> which is used for two purposes:
>>>>>
>>>>> 1) Set some properties automatically (to enable OGM's naming strategy
>>>>> and
>>>>> query translator etc., use a specific mass indexer for Hibernate
>>>>> Search)
>>>>> 2) Provide an entry point into the API for setting store specific
>>>>> options,
>>>>> e.g. like so:
>>>>>
>>>>>    OgmConfiguration ogmCfg = ...;
>>>>>    ogmCfg.configureOptionsFor( MongoDB.class )
>>>>>        .entity( GolfPlayer.class )
>>>>>            .writeConcern( WriteConcernType.REPLICA_ACKNOWLEDGED );
>>>>>
>>>>> We'll need a way to still do 1).
>>>>>
>>>>> 2) is not really required. We provide an alternative anyways, for cases
>>>>> where you don't bootstrap OGM yourself. You can specify a callback
>>>>> class
>>>>> via configuration properties, which then will be invoked and provides
>>>>> the
>>>>> entry point to the fluent API.
>>>>>
>>>>> --Gunnar
>>>>>
>>>>> [1]
>>>>>
>>>>> https://github.com/hibernate/hibernate-ogm/blob/master/core/src/main/java/org/hibernate/ogm/jpa/impl/OgmPersisterClassResolver.java
>>>>> [2]
>>>>>
>>>>> https://github.com/hibernate/hibernate-ogm/blob/master/core/src/main/java/org/hibernate/ogm/persister/impl/OgmCollectionPersister.java
>>>>> [3]
>>>>>
>>>>> https://github.com/hibernate/hibernate-ogm/blob/master/core/src/main/java/org/hibernate/ogm/cfg/OgmConfiguration.java
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> hibernate-dev mailing list
>>>>> hibernate-dev at lists.jboss.org
>>>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>>>>
>>>>> _______________________________________________
>>>>> hibernate-dev mailing list
>>>>> hibernate-dev at lists.jboss.org
>>>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>


More information about the hibernate-dev mailing list