Skip to content

Commit e032b67

Browse files
author
Phillip Webb
committed
Polish DataSourceInitialization code
Rename a few classes and methods relating to DataSourceInitialization and update the DataSourceInitializedPublisher to check for Hibernate settings.
1 parent 38af1c2 commit e032b67

File tree

10 files changed

+282
-231
lines changed

10 files changed

+282
-231
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,21 @@
5151
*/
5252
@Configuration
5353
@ConditionalOnClass(EmbeddedDatabaseType.class)
54-
@Import(DataSourceInitialization.class)
5554
@EnableConfigurationProperties(DataSourceProperties.class)
5655
public class DataSourceAutoConfiguration {
5756

5857
public static final String CONFIGURATION_PREFIX = "spring.datasource";
5958

59+
@Autowired
60+
private DataSourceProperties properties;
61+
6062
@Autowired(required = false)
6163
private DataSource dataSource;
6264

63-
@Autowired
64-
private DataSourceProperties properties;
65+
@Bean
66+
public DataSourceInitializer dataSourceAutoConfigurationInitializer() {
67+
return new DataSourceInitializer();
68+
}
6569

6670
/**
6771
* Determines if the {@code dataSource} being used by Spring was created from

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitialization.java

Lines changed: 0 additions & 169 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.jdbc;
18+
19+
import javax.sql.DataSource;
20+
21+
import org.springframework.context.ApplicationEvent;
22+
23+
/**
24+
* {@link ApplicationEvent} used internally to trigger {@link DataSource} initialization.
25+
* Initialization can occur when {@literal schema-*.sql} files are executed or when
26+
* external libraries (e.g. JPA) initialize the database.
27+
*
28+
* @author Dave Syer
29+
* @see DataSourceInitializer
30+
* @since 1.1.0
31+
*/
32+
@SuppressWarnings("serial")
33+
public class DataSourceInitializedEvent extends ApplicationEvent {
34+
35+
/**
36+
* Create a new {@link DataSourceInitializedEvent}.
37+
* @param source the source {@link DataSource}.
38+
*/
39+
public DataSourceInitializedEvent(DataSource source) {
40+
super(source);
41+
}
42+
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.jdbc;
18+
19+
import java.io.IOException;
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
23+
import javax.annotation.PostConstruct;
24+
import javax.sql.DataSource;
25+
26+
import org.apache.commons.logging.Log;
27+
import org.apache.commons.logging.LogFactory;
28+
import org.springframework.beans.factory.annotation.Autowired;
29+
import org.springframework.context.ApplicationContext;
30+
import org.springframework.context.ApplicationListener;
31+
import org.springframework.core.io.Resource;
32+
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
33+
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
34+
import org.springframework.util.StringUtils;
35+
36+
/**
37+
* Bean to handle {@link DataSource} initialization by running {@literal schema-*.sql} on
38+
* {@link PostConstruct} and and {@literal data-*.sql} SQL scripts on a
39+
* {@link DataSourceInitializedEvent}.
40+
*
41+
* @author Dave Syer
42+
* @author Phillip Webb
43+
* @since 1.1.0
44+
* @see DataSourceAutoConfiguration
45+
*/
46+
class DataSourceInitializer implements ApplicationListener<DataSourceInitializedEvent> {
47+
48+
private static Log logger = LogFactory.getLog(DataSourceInitializer.class);
49+
50+
@Autowired
51+
private ApplicationContext applicationContext;
52+
53+
@Autowired(required = false)
54+
private DataSource dataSource;
55+
56+
@Autowired
57+
private DataSourceProperties properties;
58+
59+
private boolean initialized = false;
60+
61+
@PostConstruct
62+
protected void initialize() {
63+
if (!this.properties.isInitialize()) {
64+
logger.debug("Initialization disabled (not running DDL scripts)");
65+
return;
66+
}
67+
if (this.dataSource == null) {
68+
logger.debug("No DataSource found so not initializing");
69+
return;
70+
}
71+
runSchemaScripts();
72+
}
73+
74+
private void runSchemaScripts() {
75+
List<Resource> scripts = getScripts(this.properties.getSchema(), "schema");
76+
if (!scripts.isEmpty()) {
77+
runScripts(scripts);
78+
this.applicationContext.publishEvent(new DataSourceInitializedEvent(
79+
this.dataSource));
80+
}
81+
}
82+
83+
@Override
84+
public void onApplicationEvent(DataSourceInitializedEvent event) {
85+
// NOTE the even can happen more than once and
86+
// the event datasource if not used here
87+
if (!this.initialized) {
88+
runDataScripts();
89+
this.initialized = true;
90+
}
91+
}
92+
93+
private void runDataScripts() {
94+
List<Resource> scripts = getScripts(this.properties.getData(), "data");
95+
runScripts(scripts);
96+
}
97+
98+
private List<Resource> getScripts(String locations, String fallback) {
99+
if (locations == null) {
100+
String platform = this.properties.getPlatform();
101+
locations = "classpath*:" + fallback + "-" + platform + ".sql,";
102+
locations += "classpath*:" + fallback + ".sql";
103+
}
104+
return getResources(locations);
105+
}
106+
107+
private List<Resource> getResources(String locations) {
108+
List<Resource> resources = new ArrayList<Resource>();
109+
for (String location : StringUtils.commaDelimitedListToStringArray(locations)) {
110+
try {
111+
for (Resource resource : this.applicationContext.getResources(location)) {
112+
if (resource.exists()) {
113+
resources.add(resource);
114+
}
115+
}
116+
}
117+
catch (IOException ex) {
118+
throw new IllegalStateException("Unable to load resource from "
119+
+ location, ex);
120+
}
121+
}
122+
return resources;
123+
}
124+
125+
private void runScripts(List<Resource> resources) {
126+
if (resources.isEmpty()) {
127+
return;
128+
}
129+
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
130+
populator.setContinueOnError(this.properties.isContinueOnError());
131+
populator.setSeparator(this.properties.getSeparator());
132+
for (Resource resource : resources) {
133+
populator.addScript(resource);
134+
}
135+
DatabasePopulatorUtils.execute(populator, this.dataSource);
136+
}
137+
138+
}

0 commit comments

Comments
 (0)