2012-07-27 13 views
8

Załóżmy, że mam następujący plik persistence.xml z adresem URL połączenia, użytkownik & wszystkie hasła są zakodowane na stałe.Dynamiczne ustawianie właściwości trwałości JPA

Poniższy przykład dotyczy Hibernate 3.2. W przypadku Hibernate 3.5 ++ musimy zmienić "hibernate.connection" na "javax.persistence". Ale pozwól mi zadać to pytanie niezależnie od literałów "hibernate.connection" lub "javax.persistence".

<persistence-unit name="obamacare" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <exclude-unlisted-classes>false</exclude-unlisted-classes> 
    <properties> 
    <property name="hibernate.archive.autodetection" value="class, hbm"/> 
    <property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/> 
    <property name="hibernate.connection.url" value="blah blah blah"/> 
    <property name="hibernate.connection.username" value="careuser"/> 
    <property name="hibernate.connection.password" value="carepass"/> 
    <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/> 
    <property name="hibernate.show_sql" value="true"/> 
    </properties> 
    </persistence-unit> 
</persistence> 

Jednak musimy ustawić URL, hasło użytkownika & dynamicznie. Istnieje proponowany serwer uwierzytelniania, który obsługuje hasło użytkownika, użytkownika &. Abyśmy nie musieli indywidualnie konfigurować miriadów aplikacji internetowych, które używają jakiejś formy jdbc, hibernacji lub JPA. Poza kwestią bezpieczeństwa nie chcąc przechowywać/zarządzać hasłami w widocznych plikach tekstowych.

Jeśli chodzi o JPA, w jaki sposób mogę dynamicznie ustawić te właściwości JPA? Szukam dwóch zestawów odpowiada:

  1. rozwiązania, który jest niezależny sprzedawca JPA (TopLink, EclipseLink, hibernacja, etc) - Czy jest jakaś funkcjonalność JPA, że pozwolił mi ustawić te trzy właściwości dynamicznie?

  2. Jeśli mogę całkowicie polegać na Hibernate, poza możliwą samą aleją JPA, czy istnieje sposób na osiągnięcie tego bez angażowania Spring framework (co wydaje się ogromnym monstrum z mackami w każdym miejscu)?

Byłbym zachwycony, jeśli również chcesz rzucać się w dwóch centów/quids/rupii na JNDI i jak mogę go użyć do zastąpienia funkcjonalności właściwości persistence.xml. Jednak nie jest to priorytetowe pytanie.

+1

Większość rzeczy, które chcesz wykonać, można łatwo zrobić przy użyciu Spring. Używam Springa przez kilka tygodni i wcale nie żałuję zmiany. Wiosna wydaje się dużym obciążeniem, ale w rzeczywistości jest całkiem łatwa. – siebz0r

Odpowiedz

7

To zależy od sposobu bootstrap twój EntityManagerFactory. Każda z dwóch zdefiniowanych metod pozwala przekazać wartość java.util.Map wartości. Wartości te mają pierwszeństwo przed wartościami zdefiniowanymi w jednostce trwałości.

W "podejściu SE" nie ma problemu, ponieważ proces ładowania początkowego jest zazwyczaj kontrolowany przez aplikację: javax.persistence.Persistence#createEntityManagerFactory(String puName, Map config. Teraz możesz mieć problemy tutaj, jeśli coś innego (ahem, Wiosna) "zarządza" EMF dla ciebie ...

W "podejściu do EE" nie jestem świadomy dobrego globalnego podejścia. Ta mapa wartości nadal istnieje podczas ładowania, ale problem polega na tym, że kontener EE wywołuje tę metodę.

Jednym podejściem do specyficznego hibernacji, które działałoby w obu przypadkach, byłoby użycie opcji zmiany zmiennej konfiguracyjnej. Tak więc w swojej jednostce wytrwałości zdefiniowałbyś nazwę użytkownika lub hasło za pomocą ${some.key}, a Hibernate zastąpiłby je dla ciebie. To, czy to zadziała, naprawdę zależy od tego, jak chcesz ostatecznie ustawić te wartości; Hibernate nadal potrzebuje dostępu do wartości konfiguracyjnej o nazwie some.key, aby działało ...

Jeszcze inne "podejście globalne" ... "Podejście EE" do ładowania EMF polega na tym, że pojemnik tworzy instancję javax.persistence. spi.PersistenceProvider i wywołaj jego javax.persistence.spi.PersistenceProvider # createContainerEntityManagerFactory. createContainerEntityManagerFactory ma tutaj interesujący podpis. Zasadniczo jest przekazywana javax.persistence.spi.PersistenceUnitInfo, który jest reprezentacją obiektu analizowanej jednostki utrwalania plus kilka innych rzeczy. Opcją byłoby użycie tego podejścia do bootstrap i przekazanie instancji javax.persistence.spi.PersistenceUnitInfo, abyś sam zbudował. javax.persistence.spi.PersistenceProvider to interfejs. Aby utworzyć instancję, musisz znać dostawcę, którego chcesz użyć, oraz FQN do ich impl. Ale to zwykle nie stanowi problemu, ponieważ są one dość dobrze znane.

Pytasz o tworzenie/łączenie połączeń JDBC. Tam masz dodatkowe opcje. Możesz mieć swoją "usługę poświadczeń" tworzyć DataSources i twój dostawca JPA po prostu korzystać z tego źródła danych. Wszyscy dostawcy JPA wspierają lokalizowanie DataSources przez wyszukiwanie JNDI. W "ładowaniu EE" dostawców można również przekazać DataSource do użycia przez PersistenceUnitInfo # getJtaDataSource i/lub PersistenceUnitInfo # getNonJtaDataSource. Hibernacja na przemian akceptuje instancję DataSource zamiast typowego ustawienia nazwy JNDI DataSource. Jeśli nie chcesz używać DataSource (z jakiegoś dziwnego powodu), alternatywą specyficzną dla Hibernacji jest implementacja Hibernate's ConnectionProvider, to jest umowa (interfejs) Hibernate używa do uzyskiwania i zwalniania połączeń JDBC, kiedy jest to konieczne. Implementując ConnectionProvider możesz skonfigurować podstawowe połączenia w dowolny sposób.

Wiele opcji :)

+0

Kolejne "globalne podejście" ... "Podejście EE" do ładowania EMF polega na utworzeniu instancji javax.persistence.spi.PersistenceProvider i wywołaniu jej javax.persistence.spi.PersistenceProvider # createContainerEntityManagerFactory. createContainerEntityManagerFactory ma tutaj interesujący podpis. Zasadniczo jest przekazywana javax.persistence.spi.PersistenceUnitInfo, która jest reprezentacją obiektu analizowanej jednostki uporczywości plus kilka innych rzeczy. Opcją byłoby użycie tego podejścia do bootstrap i przekazanie w javax.persistence.spi.PersistenceUnitInfo, że konstruujesz swoje własne –

+0

Zabrakło miejsca w ostatnim komentarzu :) javax.persistence.spi.PersistenceProvider to interfejs. Aby utworzyć instancję, musisz znać dostawcę, którego chcesz użyć, oraz FQN do ich impl. Ale to zwykle nie stanowi problemu, ponieważ są one dość dobrze znane. –

+0

Steve, dzięki za twój wysiłek. Czy istnieje możliwość przeniesienia komentarzy do obszaru odpowiedzi? Metoda podstawiania $ {some.key} jest dokładnie tym, czego szukam. Czy możesz dać mi przykład, jak to zrobić w pliku persistence.xml programu hibernate. Ponieważ nasze pudełko produkcyjne to jboss 4.x, musimy używać hibernacji 3.2 zamiast hibernacji 3.6 - więc wiele nowszych funkcji hibernacji nie ma zastosowania. –

3

Na drugie pytanie mogę podać rozwiązanie tylko w trybie hibernacji.

package dev.stackoverflow; 

import java.util.Properties; 

import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.cfg.Configuration; 

public class DynamicHibernateSessionFactory { 
    public Session setProperties(final String provider, 
           final Boolean excludeUnlisted, 
           final Properties properties) { 
     properties.setProperty("provider", provider); 
     properties.setProperty("exclude-unlisted-classes", excludeUnlisted.toString()); 
     Configuration configuration = new Configuration(); 
     configuration.setProperties(properties); 
     SessionFactory sessionFactory = configuration.configure().buildSessionFactory(); 
     return sessionFactory.openSession(); 
    } 
} 
Powiązane problemy