2010-03-14 4 views
7

Ich möchte einen "First Access Database Setup Process" in meiner Spring-Anwendung machen und das Einzige, was ich mir vorstellen kann, wäre, die DataSource-Bean programmatisch zu initialisieren.DataSource-Bean auf Code definieren

Meine aktuelle Bean ist wie folgt definiert:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/catalog" /> 
    <property name="username" value="condominium" /> 
    <property name="password" value="password" /> 
    <property name="validationQuery" value="SELECT 1" /> 
    <property name="testOnBorrow" value="true" /> 
    <property name="defaultAutoCommit" value="false" /> 
    <property name="maxWait" value="5000" /> 
</bean> 

aber die ideale Sache war es in von mir zu laden, wenn ich es brauche und mit dem Parameter I definieren.

Das Szenario ist, dass der Benutzer (Administrator) zum ersten Mal zur Anwendung kommt und ich ihn bitten, den Server, Port und Katalog zu verbinden. Ich speichere es in einer versenkten Datenbank und beim nächsten Start der Anwendung kann ein Bean überprüfen, ob der Parameter in der eingebetteten Datenbank gesetzt ist, und es erneut laden.

Ist es möglich?

EDT: pro @axtavt sugestion Ich bin goin mit einem Proxy ...

<bean id="dataSource" class="org.springframework.aop.framework.ProxyFactoryBean"> 
    <property name="targetSource" ref="swappableDataSource"/> 
</bean> 
<bean name="swappableDataSource" class="org.springframework.aop.target.HotSwappableTargetSource"> 
    <constructor-arg ref="dummyDataSource"/> 
</bean> 
<bean id="dummyDataSource" factory-bean="dataSourceFactory" factory-method="createDataSource" destroy-method="close"/> 
<bean id="dataSourceFactory" class="com.condominium.spring.factory.DataSourceFactory"/> 

einmal mit einem Proxy implementiert, wie kann ich es auf die ursprüngliche Bean werfen?

Object o = ctx.getBean("dataSource"); 
BasicDataSource ds = (BasicDataSource)o; 

wird werfen einen java.lang.ClassCastException: $ Proxy4 nicht org.apache.commons.dbcp.BasicDataSource gegossen werden kann

+0

http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.html könnte, aber ich # M nicht sicher helfen, ob es Strom ist – stacker

+0

gefunden: es handelt sich mehr um eine austauschbare Datenquelle mit einem Proxy. http://affy.blogspot.com/2007/11/dynamic-datasource-via-spring-using.html –

Antwort

2

können Sie eine Fabrik erstellen DataSource zu produzieren, wie Sie wollen:

<bean id = "dataSourceFactory" class = "MyFactory" /> 

<bean id = "dataSource" factory-bean = "dataSourceFactory" factory-method = "createDataSource" /> 

-

public class MyFactory { 
    public DataSource createDataSource() { 
     ... // produce a DataSource 
    } 
} 
+0

So sollte ich auch EntityManger von einer Fabrik erstellen oder? Denn jetzt ist es in der .xml definiert und hängt von der Datenquelle ab –

+0

Da die Fabrik im Kontext definiert wird, werden wir nicht in das gleiche Problem fallen? –

+0

@Ruben: Nein, sollten Sie nicht. Dieses Snippet erstellt eine Bean mit dem Namen 'dataSource'. Diese Bohne kann wie jede andere Bohne verwendet werden. Der einzige Unterschied ist, dass Spring Ihren eigenen Fabrikcode aufruft, um ihn zu instanziieren. – axtavt

1

können Sie die Datenbankverbindungseigenschaften externalisieren:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
    <property name="driverClassName" value="${driver}" /> 
    <property name="url" value="${url}" /> 
    <property name="username" value="${username}" /> 
    <property name="password" value="${password}" /> 
    <property name="validationQuery" value="SELECT 1" /> 
    <property name="testOnBorrow" value="true" /> 
    <property name="defaultAutoCommit" value="false" /> 
    <property name="maxWait" value="5000" /> 
</bean> 

Jetzt Spring wird sie aus einer Datei .properties erhalten, die beim Start geladen wird.

Eine weitere Sache, an die Sie denken sollten, wenn Sie einen Java EE-Anwendungsserver verwenden, ist der JNDI-Verbindungspool. Sie haben den JNDI-Namen externalisiert, und die Verbindungsparameter werden vom Administrator des Anwendungsservers verwaltet. Ich würde sagen, dass dies der bevorzugte Weg ist. Im Moment haben Sie noch ein Passwort im Klartext - eine schlechte Idee.

+0

Es ist ein Punkt, aber in meinem Fall brauche ich (der Benutzer benötigt), um es zur Laufzeit zu definieren. Ich werde nie wissen, wo der Benutzer sich verbinden möchte. Ich benutze Kater. –

+0

@duffymo könnten Sie bitte erklären, wo der Name der Eigenschaftendatei konfiguriert ist – stacker

+0

Tomcat unterstützt JNDI benannte Datenquellen. Du musst etwas wissen. Unabhängig davon, müssen Sie den Server aufspringen, um die Änderungen zu erhalten, da Spring den App-Kontext beim Start liest. – duffymo

0

Ich bin mit genau den gleichen Proxy-Ansatz, wie Sie erwähnt. Um loszuwerden java.lang.ClassCastException Sie können DataSource von HotSwappableTargetSource Bean wie unten erhalten.

HotSwappableTargetSource swapper = ctx.getBean(HotSwappableTargetSource.class); 
BasicDataSource ds = (BasicDataSource) swapper.getTarget();