On Wed, Oct 3, 2012 at 9:44 AM, Vincent Massol <vincent(a)massol.net> wrote:
  Hi Andreas,
 On Oct 3, 2012, at 9:22 AM, Andreas Jonsson <aj(a)member.fsf.org> wrote:
  +1 for extensible entity mappings.
 When registering a new mapping, i think that it should be possible to
 specify if it should apply to a particular wiki or to the whole farm.
 The collection of mappings for the whole farm should of course be
 enabled for new wiki instances. 
 Indeed that's a possibility and it'll almost work OOB with my proposal
 since an extension can be installed only on a subwiki for ex. However it
 would also require:
 * ability to register core extensions for a given wiki
 * have a session factory per wiki
 
If you use different session factories, there is no point to prefix
mapping, and moreover this does not provide what Andreas expects, a single
session across multiple databases.
 And that's more complex. I'd like to finish my refactoring first and this
 could be added later on if we agree about it since it won't impact much
 what I'm working on.
 (see below)
  While we are at it, we should try to find a
better way to implement
 virtual wikis.  As I've already mentioned, I believe that this can be
 achieved by reregistering entity mappings per wiki, with prefixed entity
 names.  (This would really be the same as extensible entity mappings.)
 It seems that this should enable access to multiple wikis within the
 same Hibernate session, while being fully backwards compatible with the
 current implementation. 
 
I do not see how you expect to switch the accessed database during the
session ?
 
 But Denise wrote "[...] I doubt you will reach soon a state where
 hibernate support sessions across databases." and I'm not sure if he
 knows something about Hibernate limitations that would prevent this
 solution. 
  
Accessing multiple database in a single session is like seeing multiple
database as a single one. I doubt hibernate will provide such
implementation, since this is absolutely not the goal of that framework.
The only potential implementation I could foresee to fulfill that needs, is
a relaxed version of the upcoming multi-tenancy discriminator strategy,
that would allow accessing the database without using the discriminator.
But in that scenario, you would have only one database, so this not really
what you expect.
 
 The XML-schema for entity mappings allows for both a schema and catalog
 attributes to the class element.  If this is implemented in the expected
 way, it should work to use mapping templates such as:
    <class name="${entityNamePrefix}:com.xpn.xwiki.doc.XWikiDocument"
           table="xwikidoc" schema="${entitySchemaAttribute}">
 and for MySQL
    <class name="${entityNamePrefix}:com.xpn.xwiki.doc.XWikiDocument"
           table="xwikidoc" catalog="${entityCatalogAttribute}">
 And then you implement an EntityNamingStrategy for selecting the correct
 mappings for the current wiki. 
 BTW another solution could be to not any issue any schema change but to
 have hibernate prefix all queries with the schema/catalog/user, e.g.
 "select * from <dbname>.<table>". I couldn't find any built in
support for
 this but it could be possible to plug a new strategy - would need to ask
 them.
 
 
I doubt this would really works in all kind of DB engines.
  Thanks
 -Vincent
  Best Regards,
 /Andreas
 2012-10-02 20:53, Vincent Massol skrev:
> Hi devs,
>
> I'd like to propose the following to implement 
http://jira.xwiki.org/browse/XWIKI-8271:
 >
> * Create a new xwiki-platform-store-hibernate module
> * Add a Component role: HibernateConfiguration implements Comparable
> * API: void HibernateConfiguration.configure(Configuration 
aggregatedConfiguration), where the passed aggregatedConfiguration contains
 the configuration filled by all the HibernateConfiguration.configure()
 calls executed before
 > * Add a
HibernateConfigurationManager.getConfiguration() component that 
 is in charge of
loading the various HibernateConfiguration in the correct
 order
 > * Have an AbstractHibernateConfiguration
implements 
  HibernateConfiguration with 1 API: getDatabaseType(Configuration
 configuration). It gets the DB type from the connection URL string and
 returns a DatabaseType object which represents the database type
 >
> * CoreHibernateMapping (hint = "xwiki") <==> xwiki.hbm.*.xml -
highest 
 priority, defines the connection URL among other props
 > * ActivityStreamHibernateMapping (hint =
"activitystream")
> * FeedHibernateMapping (hint = "feeds")
>
> Note 1: If a HibernateConfiguration impl needs to load mappings that 
 depend on
the DB they call AbstractHibernateConfiguration.
 getDatabaseType() to get the DB.
 > Note 2: If the user wants to use a different
HBM file, he/she just has 
 to put a file with the same name (e.g. xwiki.hbm.xml) in
WEB-INF/classes
 > Note 3: This means we won't put any
mapping anymore in the 
 hibernate.cfg.xml file since it's not needed anymore
(although it would
 continue to work if you put mappings there).
 >
> Usage:
>
> @Inject
> HibernateConfigurationManager configurationManager;
>
> Configuration configuration = configurationManager.getConfiguration();
> SessionFactory sessionFactory = configuration.buildSessionFactory();
>
> Then all that remains to implement 
 http://jira.xwiki.org/browse/XWIKI-8271 is
to have a component singleton
 that will be in charge of returning the SessionFactory and which can be
 asked to rebuild a new SessionFactory (using a new Configuration).
 >
> We'll just need to decide how we trigger this. 2 options:
> * By using an Event Listener listening on HibernateConfiguration 
 registrations
and recreating automatically a new SessionFactory when it
 happens. Cons: if an extension contributes several HibernateConfiguration
 then Hibernate will be reinitialized several times
 > * By listening to an Event sent by the
Extension Manager when an 
 extension has finished loading and somehow find out all
the
 HibernateConfiguration that have been added (several ways of doing this)
 and recreating the SessionFactory
 >
> Note: The only issue I can foresee is if a Hibernate call is in 
 progress in
one thread when an extension is installed and a new
 SessionFactory is created at the same time. Either we don't care or we
 could implement retry at the DB level, or we could introduce some semaphore
 so that we start the reinit only when nobody has a lock on the
 SessionFactory, or…
 >
> WDYT? 
 
Are you excluding the possibilities to use hibernate annotations, or do you
expect to implements that in addition to an HibernateConfiguration
implementation ?
  >
> Of course, the pros is those listed in 
http://jira.xwiki.org/browse/XWIKI-8271:
 > * Ability for a platform module to contribute
Hibernate mappings 
 (static)
 > * Ability for an extension installed at
runtime to contribute Hibernate 
 mappings (dynamic)
 >
> Note that the reason I'm starting all this is because I'd like to 
implement 
http://jira.xwiki.org/jira/browse/XWIKI-7953 cleanly in a
 module separate from oldcore.
 >
> Thanks
> -Vincent 
 _______________________________________________
 devs mailing list
 devs(a)xwiki.org
 
http://lists.xwiki.org/mailman/listinfo/devs
  
IMO, we should avoid pursuing with hacks over our Hibernate implementation.
I am more in favor to remove our current, really underused custom solution,
which is really expensive in maintenance compare the their real usage. In
comparison, your proposal seem more clean, and a bit less dynamic. I do not
think going too far and being too smart to be dynamic is really important.
Providing extension a way to register their hibernate mapping, and at some
point during wiki startup, building the hibernate session factory in a
single step would be the cleanest and most efficient solution. When one or
some new extensions are installed, and one or some of these extensions have
registered an additional hibernate mapping, rebuilding the session factory
once at the end of the installation would probably be the best.
In regards to your proposal, if I well understand it, I am not sure the way
you expect to chain the call to the configure() method is nice. It will
implies that order could matter. While this would allow the ability to
modify a configuration previously made, you will have no way to ensure such
configuration has been made before. So there is no point to provide
the aggregated configuration, unless you may ensure ordering. Maybe I have
overlooked something ?
--
Denis Gervalle
SOFTEC sa - CEO
eGuilde sarl - CTO