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
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.
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.
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.
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?
>
> 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