[hibernate-dev] SessionFactory building APIs

Gunnar Morling gunnar at hibernate.org
Thu Mar 26 04:05:43 EDT 2015


2015-03-26 0:21 GMT+01:00 Steve Ebersole <steve at hibernate.org>:

> On Wed, Mar 25, 2015 at 4:57 PM, Gunnar Morling <gunnar at hibernate.org>
> wrote:
>
>> > 1) What do you think of the split in MetadataSources and
>> MetadataBuilder?
>> > Does the aplit make sense?  Or does it make more sense to combine them
>> into
>> > one contract?
>>
>> I think the split makes sense, as I understand that there are two
>> different "phases" of configuration here:
>>
>> * add multiple sources of configuration (XML files, annotated classes)
>> * apply further configuration (naming strategy etc.)
>>
>
>> Assuming one first needs to configure all the sources before applying the
>> configuration from the second category, it seems useful to express that in
>> the API.
>>
>
> MetadataSources is used to collect the sources of mapping information.
> However, its really not necessary that the split exists in terms of "this
> needs to be set before that".  Its more a functional split because they
> each serve different roles.  One collects the sources of metadata
> information.  One builds that into a Metadata object (based on some config).
>

I see. Also if it's not strictly needed, I kind of like the split, as it
enforces some structuring of client code which should help with readability.


> The name "MetadataSources" made me stumble a bit, though. Generally I find
>> pluralized class names a bit odd, only really useful for either
>> collection-like classes or static helper classes dealing with a specific
>> type (e.g. Strings, Collections). What would you think about
>> MetadataSources not being a top-level class itself, but rather an inner
>> class of MetadataBuilder (e.g. named MetadataBuilderContext) which is
>> returned by a static creator method on MetadataBuilder:
>>
>> MetadataBuilder builder = MetadataBuilder.configure() // returns
>> MetadataBuilderContext
>>     .addFile(...)
>>     .addAnnotatedClass(...)
>>     .addResource(...)
>>     .getBuilder();
>>
>> IMO that would help users a bit to find the right entry point.
>>
>
> Not sure about the naming.  I think MetadataSources is much better than MetadataBuilderContext.
> That's my take.  We can see what others think.
>
> As far as the API, I am ok with changing that up if others agree.  I could
> see something like:
>
> MetadataBuilder.defineSources()
>     .addFile(...)
>     .addAnnotatedClass(...)
>     .addResource(...)
>     .getBuilder();
>
> defineSources (or whatever we call it) needs to be overloaded to be able
> to accept a ServiceRegistry:
>
> MetadataBuilder.defineSources()
>
> versus:
>
> MetadataBuilder.defineSources( new
> StandardServiceRegistryBuilder()...build() )
>

Ok.

>
>> Some more questions/thoughts:
>>
>> * Who is the intended client for the getter methods on MetadataSources?
>> Only ORM, or also user code? In case of the former, should the public MetadataSources
>> contract be an interface with the addXy() methods only, whereas getters are
>> only accessible via an internal implementation class? That would narrow
>> down the exposed API.
>>
>
> Yes, the intended usage is just Hibernate itself.  However, the exposure
> is just a natural follow on of the design that MetadataSources is a class
> that one instantiates directly.  Can't instantiate an interface of course.
> An approach such as above addresses that.
>

Yes, it would be nice to hide all those methods from the API which are not
intended for the user.


> * Are MetadataSources#addAttributeConverter(),
>> addAuxiliaryDatabaseObject() and addSqlFunction() adding a *source* for
>> meta-data really? Somehow it seems they should rather be located on
>> MetadataBuilder?
>>
>
> From one perspective yes.  Not *sources* per-se, but they are things that
> the user supplies that become part of the Metadata; as opposed to simply
> options that are used during the process of building a Metadata
> (MetadataBuilder).  And especially since you want to rename "sources" to
> "building context"; imo that makes the argument that these belong here even
> stronger.
>
>
>
>> * I don't think MetadataSources is intended for concurrent usage from
>> several threads, right? If so, it should not be needed to have a
>> ConcurrentHashMap as a member
>>
>
> True.  Not sure why it stores those in ConcurrentHashMap...
>
>
>
>> * MetadataSources#addInputStream() et al.: What schema have passed
>> streams to adhere to? Are these orm.xml, hbm.xml or both? Would be nice to
>> have this documented
>>
>
> Well same is true of addResources, addFile, add..  I get what you are
> saying, but why do you single out addInputStream here?
>

That was only one example, it applies to others as well.


>   To be honest, I would personally love to get rid of addInputStream.  I
> think addInputStreamAccess(InputStreamAccess) is a MUCH better solution
> there.
>

Not sure, that would require to invoke another method/ctor to obtain the
ISA from whatever type the user wishes to add, right? I think it's easier
on the user if they can pass their input type directly.

Speaking of it, I see there is
MetadataSources#addInputStream(InputStreamAccess) already. ISA lives in
*.spi, though. IMO the API should not leak SPI types in signatures.

Btw. could you also add addPackage(Package), so one can do

    addPackage( MyEntity.class.getPackage() )

?

* MetadataBuilder#setSourceProcessOrdering: May be a bit nicer to use if
>> modelled with var-args:
>>
>>     sourceTypeProcessingOrder(MetadataSourceType first,
>> MetadataSourceType... others) -> used like sourceTypeProcessingOrder(
>> CLASS, HBM );
>>
>
>
> +1
>
>


More information about the hibernate-dev mailing list