I need to execute SQL
script before PropertyPlaceholderConfigurer
is initialized in Spring's context, as soon as application properties are stored in the database and this script should insert them. But currently placeholder is initialized earlier, which leads to errors.
Is there a way to execute <jdbc:initialize-database data-source="dataSource" ...
before <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" ...
in Spring?
Or is there a way to initialize placeholderConfig
bean later? I tried to use depends-on
, lazy-init
attributes for this bean, but it didn't help. Thanks in advance.
Another solution without creating any Bean:
If you've got one <jdbc:initialize-database />
you can add this property depends-on="org.springframework.jdbc.datasource.init.DataSourceInitializer#0"
to your bean <bean id="placeholderConfig" />
If you have more than one <jdbc:initialize-database />
adapt the #0
.
Here is how I solved that. I created a class Initializer
. This class in its constructor executes plain old sql statements (java.sql.Statement
), creates table (if it doesn't exist), and inserts properties (if they are not there). The dataSource
bean is passed in the context to this constructor, and placeholderConfig
bean uses depends-on="initializerBean"
. So, properties appear in the database before they are used.
This script
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc">
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:database/drop_schema.sql" />
<jdbc:script location="classpath:database/create_schema.sql" />
<jdbc:script location="classpath:database/sample_data.sql"/>
</jdbc:initialize-database>
<!-- Other bean definitions -->
</bean>
is essentially a shortcut to
<bean class="org.springframework.jdbc.datasource.init.DataSourceInitializer" id="dataSourceInitializer">
<property name="databasePopulator" ref="resourceDatabasePopulator"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="resourceDatabasePopulator"
class="org.springframework.jdbc.datasource.init.ResourceDatabasePopulator">
<property name="scripts">
<array>
<value>classpath:database/drop_schema.sql</value>
<value>classpath:database/create_schema.sql</value>
<value>classpath:database/sample_data.sql</value>
</array>
</property>
</bean>
Note that I've added id to the DataSourceInitializer bean. Now you can reference it in PropertyPlaceholderConfigurer's depends-on
attribute. That way you declare that your PropertyPlaceholderConfigurer should be created after DataSourceInitializer.
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="dataSourceInitializer"/>
In my case db was initialized after the LocalContainerEntityManagerFactoryBean had been created and Hibernate was unable to validate my schema.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With