[hibernate-dev] Bytecode enhanced, Reference Cached immutable Entities
Steve Ebersole
steve at hibernate.org
Fri Mar 27 07:35:16 EDT 2015
An EntityPersister describes each entity you defined in your model. Its
one-to-one between @Entity and EntityPersister. And really, it is totally
reasonable to have the EntityPersister determine the "EntityEntry builder"
to use. That also eliminates needing to develop
yet-another-extension-point because if we expose it from EntityPersister
OGM already swaps EntityPersister impls so this would JustWork.
On Fri, Mar 27, 2015 at 6:04 AM, John O'Hara <johara at redhat.com> wrote:
> On 26/03/15 16:22, Steve Ebersole wrote:
>
> The contract I suggested btw is missing one use case I know we have
> discussed in regards to OGM a few times... the ability to store references
> to datastore specific locators (I think the use case was to efficiently
> load collections through that datastore reference). But that (obviously)
> requires passing extra, specific state into the createEntityEntry method.
> Not really sure the best way to handle such things tbh.
>
> If we did have a "creation Context" parameter passed to the
> createEntityEntry, we would be instantiating more objects, however if we
> went with Sanne' suggestion if caching the EnityEntryFactory with the
> EntityPersister, how many objects would be actually created? I am not sure
> about the relationship between Entity, EntityEntry and Session but could
> this a possibility if there is a 1-1 relationship between EntityPersister
> and no. of different Entities definitions?
>
>
> On Thu, Mar 26, 2015 at 11:16 AM, Steve Ebersole <steve at hibernate.org>
> wrote:
>
>> Apparently I hit some key combo that means send :) To finish up...
>>
>> On Thu, Mar 26, 2015 at 10:58 AM, Steve Ebersole <steve at hibernate.org>
>> wrote:
>>
>>>
>>> On Thu, Mar 26, 2015 at 10:20 AM, Sanne Grinovero <sanne at hibernate.org>
>>> wrote:
>>>>
>>>>
>>>> Concurrency
>>>> Since the goal is to share the ImmutableEntityEntry instance among
>>>> multiple threads reading it, I'd rather make sure that it is really
>>>> immutable. For example it now holds onto potentially lazy initialized
>>>> fields, such as getEntityKey().
>>>> If it's not possible to make it really immutable (all final fields),
>>>> we'll need to make it threadsafe and question the name I'm proposing.
>>>>
>>>
>>> The specific use-case John is interested in does indeed need to be
>>> completely thread-safe and fully concurrent.
>>>
>>>
>>>> LockMode
>>>> From a logical perspective of users, one might think that an entity
>>>> being "immutable" doesn't necessarily imply I can't lock on it..
>>>> right? I'm not sure how far it could be a valid use case, but these
>>>> patches are implying that one can't lock an immutable entity anymore,
>>>> as the lock state would be as immutable as anything else on the
>>>> EntityEntry.
>>>> Are we good with that? Alternatively one might need to think to
>>>> separate the lock state handling from the EntityEntry.
>>>>
>>>
>>> Conceptually there is nothing wrong with requesting a READ lock on an
>>> immutable entity. But like you said, what is the logical expectation
>>> there? IMO there should be none. But if we decide that it is OK to req
>>>
>>
>> But if we decide that it is OK to request a lock on an immutable
>> entity, that is problematic for the idea of a "SharedEntityEntry" or an
>> "ImmutableEntityEntry" because a lock is associated with a Session which is
>> what the EntityEntry is meant to model... an entity's information in
>> relation to a Session. Aka, it now needs to hold state.
>>
>>
>>
>>> Notice I said immutable here and not READ_ONLY which is a specific
>>> distinction which is important to other parts of your email that I will
>>> address in a second email.
>>>
>>>
>>>
>>>>
>>>> On smaller details:
>>>> # org.hibernate.engine.internal.SharedEntityEntry is hosted in an
>>>> .internal package, I don't think it's right to refactor all the public
>>>> API javadoc which was referring to EntityEntry to now refer to the
>>>> internal implementation.
>>>> # things like EntityEntryExtraState should probably get moved to
>>>> .internal packages as well now - we couldn't do that before without
>>>> breaking either encapsulation or APIs.
>>>>
>>>
>> +1
>>
>>
>>>
>>>> In terms of git patches, the complexity of the changeset risks to get
>>>> a bit our of hand. What about we focus on creating a clean pull
>>>> request which focuses exclusively on making EntityEntry an interface,
>>>> and move things to the right packages and javadoc?
>>>>
>>>
>> Agree 100%
>>
>>
>>> You'd have a trivial EntitEntryFactory, and we can then build the
>>>> evolution on top of that, not least maybe helping out by challenging
>>>> some points in parallel work.
>>>> These are the things I'd leave for a second iteration:
>>>> - add various implementations of EntityEntry iteratively, as needed
>>>> - the strategy such a Factory would use the pick an implementation
>>>> - ultimately, make it possible for an integrator to override such a
>>>> Factory
>>>>
>>>
>> This all seems reasonable. For 5.0 I think the most important thing
>> is to nail down the idea of EntityEntry as an interface, introduce a
>> Factory for building them and agree on the signature for building them.
>> Granted we may need iteration to finalize the actual Factory signature,
>> especially as OGM finally starts to use it, but I think that in general we
>> can get it pretty close. Worst case we just pass high-level constructs
>> like the EntityPersister (which OGM supplies custom impls) and the Session
>> and all the "EntityEntry state". For the purpose of starting a discussion:
>>
>> public interface EntityEntryFactory {
>> public EntityEntry createEntityEntry(
>> PersistenceContext persistenceContext,
>> EntityPersister persister,
>> Status status,
>> Serializable id,
>> Object version,
>> Object[] loadedState,
>> Object rowId,
>> LockMode lockMode,
>> boolean existsInDatabase,
>> boolean disableVersionIncrement,
>> boolean lazyPropertiesAreUnfetched);
>> }
>>
>> I would suggest a "creation context" method param object to pass in
>> here, but seeing as how we are trying to stop instantiations...
>>
>> I would prefer the definition of the EntityEntryFactory to use be
>> defined via SessionFactoryBuilder interface. I already have plans to have
>> a auto-loaded hook for integrators to be able to adjust the
>> SessionFactoryBuilder. But as a Service is fine too.
>>
>>
>>>> For example with Hibernate OGM we might want to override / re
>>>> configure the factories to use custom EntityEntry implementations -
>>>> requirements are not fully clear at this point but it seems likely.
>>>>
>>>> The priority being to define the API as that would be a blocker for
>>>> 5.0, we have then better choices to leave more smarter and advanced
>>>> EntityEntry implementations for the future; we'd still need to
>>>> implement at least the essential ones to make sure the API of the
>>>> EntityEntryFactory has all the context it needs.
>>>>
>>>> Thanks,
>>>> Sanne
>>>>
>>>>
>>>> On 24 March 2015 at 09:27, John O'Hara <johara at redhat.com> wrote:
>>>> > Steve,
>>>> >
>>>> > Have you had chance to look at this? Do you have any
>>>> comments/observations?
>>>> >
>>>> > Thanks
>>>> >
>>>> > John
>>>> >
>>>> >
>>>> > On 17/03/15 09:24, John O'Hara wrote:
>>>> >
>>>> > Steve,
>>>> >
>>>> > I have been having a think about the EntityEntry interface, and have
>>>> forked
>>>> > a branch here:
>>>> >
>>>> >
>>>> https://github.com/johnaoahra80/hibernate-orm/tree/EntityEntryInterface
>>>> >
>>>> > I know it is nowhere near complete, but was this the sort of idea you
>>>> had in
>>>> > mind?
>>>> >
>>>> > Thanks
>>>> >
>>>> > John
>>>> >
>>>> >
>>>> > On 13/03/15 09:44, John O'Hara wrote:
>>>> >
>>>> > EntityEntry retains a reference to a persistenceContext internally
>>>> that
>>>> > org.hibernate.engine.spi.EntityEntry#setReadOnly makes calls to, is
>>>> this
>>>> > where the session reference is kept? As
>>>> > org.hibernate.engine.spi.PersistenceConext is an interface could we
>>>> have a
>>>> > different implementation for this use case? e.g. an
>>>> > ImmutablePersistenceContext that could be shared across sessions?
>>>> >
>>>> > For the bytecode enhancement, could we change the enhancer so that it
>>>> adds
>>>> > an EntityEntry interface with javassist.
>>>> > ClassPool.javassist.ClassPool.makeInterface()() as opposed to adding
>>>> a class
>>>> > javassist.ClassPool.makeClass()? I need to have a look at javassit to
>>>> > confirm what javassist.ClassPool.makeInterface() does.
>>>> >
>>>> > Thanks
>>>> >
>>>> > John
>>>> >
>>>> > On 12/03/15 18:52, Steve Ebersole wrote:
>>>> >
>>>> > It is possible. Although some of the changes are particularly
>>>> painful.
>>>> > Most of EntityEntry, if it is an interface, can be made to work with
>>>> your
>>>> > use case. org.hibernate.engine.spi.EntityEntry#setReadOnly I think
>>>> is the
>>>> > one exception, because:
>>>> > 1) your use case needs it
>>>> > 2) it expects the Session to be available internally (its not passed)
>>>> >
>>>> > The bigger thing I am worried about for you is the bytecode stuff, as
>>>> that
>>>> > ties very tightly with EntityEntry.
>>>> >
>>>> _______________________________________________
>>>> hibernate-dev mailing list
>>>> hibernate-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>>>
>>>
>>>
>>
>
>
> --
> John O'Harajohara at redhat.com
>
> JBoss, by Red Hat
> Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom.
> Registered in UK and Wales under Company Registration No. 3798903 Directors: Michael Cunningham (USA), Charlie Peters (USA), Matt Parsons (USA) and Michael O'Neill (Ireland).
>
>
>
More information about the hibernate-dev
mailing list