2010-03-14 3 views
7

Je voudrais faire un "processus d'installation de la base de données First Access" dans mon application de printemps et la seule chose que je peux imaginer comme solution serait d'initialiser le bean DataSource par programme.Définir le bean DataSource sur le code

Mon haricot actuel est défini comme:

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

mais l'idéal est de le charger par moi-même dans chaque fois que je besoin et avec le paramètre I définis.

Le scénario est que l'utilisateur (administrateur) arrive à l'application à la première fois et je lui demande le serveur, le port et le catalogue pour se connecter. Je le stocke dans un db embarqué et le prochain démarrage de l'application, un bean peut vérifier si les paramètres sont définis sur la base de données intégrée et le charger à nouveau.

Est-ce possible?

EDT: par @axtavt Sugestion Je suis goin avec un 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"/> 

une fois avec une procuration mis en œuvre, comment puis-je l'ai jeté à l'original Bean?

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

lancera une java.lang.ClassCastException: Proxy4 $ ne peut pas être jeté à org.apache.commons.dbcp.BasicDataSource

+0

http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.html pourrait aider, mais je ne sais pas # M, que ce soit en cours – stacker

+0

a trouvé ceci: il s'agit plus d'une source de données swapable utilisant un proxy. http://affy.blogspot.com/2007/11/dynamic-datasource-via-spring-using.html –

Répondre

2

Vous pouvez créer une usine pour produire un DataSource comme vous voulez:

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

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

-

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

de cette façon, je devrais créer EntityManger d'une usine aussi bien? Parce que maintenant, il est défini dans le fichier .xml et dépend de la source de données –

+0

Puisque l'usine est définie dans le contexte, ne tomberons-nous pas dans le même problème? –

+0

@Ruben: Non, vous ne devriez pas. Cet extrait crée un bean nommé 'dataSource'. Ce haricot peut être utilisé comme n'importe quel autre haricot. La seule différence est que Spring appellera votre propre code d'usine pour l'instancier. – axtavt

1

Vous pouvez les propriétés de extérioriser connexion de base de données:

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

Maintenant Spring les obtiendra à partir d'un fichier .properties qui est chargé au démarrage.

Si vous utilisez un serveur d'applications Java EE, vous devez également penser au pool de connexions JNDI. Le nom JNDI sera externalisé et les paramètres de connexion seront gérés par l'administrateur du serveur d'applications. Je dirais que c'est la façon préférée de le faire. À l'heure actuelle, vous avez toujours un mot de passe en texte brut - une mauvaise idée.

+0

C'est un point, mais dans mon cas, j'ai besoin (l'utilisateur a besoin) de le définir au moment de l'exécution. Je ne saurai jamais où l'utilisateur veut se connecter. J'utilise Tomcat. –

+0

@duffymo pourriez-vous expliquer où le nom du fichier de propriétés est configuré – stacker

+0

Tomcat prend en charge les sources de données nommées JNDI. Tu devras savoir quelque chose. Quoi qu'il en soit, vous devrez faire rebondir le serveur pour obtenir les changements, car Spring lit le contexte de l'application au démarrage. – duffymo

0

J'utilise exactement la même approche proxy que vous avez mentionné. Pour se débarrasser de java.lang.ClassCastException Vous pouvez obtenir dataSource de HotSwappableTargetSource haricot comme ci-dessous.

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