2010-10-04 10 views
16

Sto scrivendo un'app Web che supporta più utenti. Ogni utente ha il proprio database - usando H2. tutti gli schemi di database sono gli stessi.Origini dati multiutente: Spring + Hibernate

Desidero utilizzare Spring + Hibernate per questa applicazione.

Così mi sono bloccato a come associare database di un utente con l'utente - forse associato nel HTTPSession, ed estendere AbstractRoutingDataSource di primavera? ma non avrebbe questo effetto la cache di Hibernate? Un altro modo è avere una SessionFactory con ogni origine dati, anche se lo schema di ogni datasource è lo stesso ... quindi lo considero uno spreco.

In ogni caso, la selezione dell'origine dati deve essere dinamica, non possono essere preconfigurati in file di contesto, poiché ogni nuovo utente avrà il proprio database creato. Esistono strutture/soluzioni esistenti?

Non so troppo su Hibernate Shards, forse funziona?

risposta

8

ho potrebbe essere sbagliato circa il (rigoroso) bisogno di avere uno SessionFactory per database, come suggerito da alcune risorse:

Mi prenderò del tempo per rileggere tutto domani (non ho avuto tutti i dettagli per essere onesti) e per comprendere appieno le implicazioni di una tale impostazione (anche se sembra chiaro che romperà la cache di secondo livello). Tornerò su questo più tardi.


Sto scrivendo una web app che supporta più utenti. Ogni utente ha il proprio database - usando H2. tutti gli schemi di database sono gli stessi.

Mi chiedo come si ridurrà ... Quanti utenti hai? Come si esegue H2, quale modalità?

Quindi sono bloccato su come associare il database di un utente a quell'utente, forse associato a HTTPSession e estendere Spring AbstractRoutingDataSource?

Dovrete costruire un SessionFactory per utente e associarlo all'utente connesso (in un Map, utilizzando il login come chiave) e quindi ottenere un Session da un dato SessionFactory. Legare il ciclo di vita della SessionFactory alla sessione HTTP sembra essere una buona idea (per risparmiare un po 'di memoria) ma non sono sicuro che Spring sarà molto utile qui. Potrei sbagliarmi ma una variazione della classe HibernateUtil e un approccio completamente programmatico sembrano più semplici. A proposito, non sono sicuro che avrai bisogno di più connessioni per utente.

ma non avrebbe questo effetto cache di Hibernate?

Quale cache?

Un altro modo è disporre di SessionFactory con ogni origine dati, anche se lo schema di ogni origine dati è lo stesso ... quindi lo considero uno spreco.

Oh, è uno spreco, ma è quello che si vuole fare (un database per utente). E non hai la scelta (hai bisogno di uno SessionFactory per base dati). Perché hai effettivamente bisogno di un database per utente? Sei sicuro che questa sia una decisione saggia? Come già accennato, questo significa molti problemi, non si adatta bene, aggiunge complessità, ecc. Perché non utilizzare un singolo database e associare i dati all'utente?

In ogni caso, la selezione dell'origine dati deve essere dinamica, non possono essere preconfigurati in file di contesto, poiché ogni nuovo utente avrà il proprio database creato. Esistono strutture/soluzioni esistenti?

Non a mia conoscenza. Questo è anche il motivo per cui penso che dovrai fare tutto in modo programmatico.

Non so troppo su Hibernate Shards, forse funziona?

Date le esigenze dinamiche della vostra applicazione, non vedo come potrebbe essere d'aiuto.

+0

Ciao Pascal, Grazie per la risposta. Tutti i database hanno lo stesso schema, quindi una SessionFactory per tutti questi database andrebbe bene. Hibernate ha una cache di secondo livello, che potrebbe contenere dati memorizzati nella cache non validi se carico 2 entità uniche da 2 database diversi ma con gli stessi ID. Penso di riuscire a far funzionare tutto associando il DataSource a una HttpSession e utilizzando un Interceptor per collegare il DataSource nella HttpSession a ThreadLocal in modo che il mio impl AbstractDataSource possa ottenere il DS corretto per la transazione. – Dzhu

+0

+1 per l'articolo di Ken DeLong - mi ha risparmiato qualche mal di testa :-) – opyate

1

Grazie all'aiuto delle 2 persone (Pascal e org.life.java)!

È possibile, ma con alcuni problemi: ad es. la cache di ibernazione di secondo livello/cache di query.

Questo link fornito da Pascal è una risorsa molto buona:

http://www.jroller.com/kenwdelong/entry/horizontal_database_partitioning_with_spring.

La mia motivazione principale per dare a ciascun utente un database separato è perché i dati probabilmente aumenteranno rapidamente, quindi è richiesto il partizionamento orizzontale.