Browse Source
Created DbcpDataSourceFactory factory bean to create and populate a dbcp based connection pool. The factory bean is based on EmbeddedDataSourceFactory from the JavaConfig version of Pet Clinic. The new DbcpDataSourceFactory has been tested with HSQL in embedded and stand-alone modes.pull/23217/head
6 changed files with 404 additions and 10 deletions
@ -0,0 +1,243 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.samples.petclinic.config; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.BufferedWriter; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.io.StringWriter; |
||||||
|
import java.sql.Connection; |
||||||
|
import java.sql.SQLException; |
||||||
|
import java.sql.Statement; |
||||||
|
|
||||||
|
import javax.sql.DataSource; |
||||||
|
|
||||||
|
import org.apache.commons.dbcp.BasicDataSource; |
||||||
|
import org.springframework.beans.factory.DisposableBean; |
||||||
|
import org.springframework.beans.factory.FactoryBean; |
||||||
|
import org.springframework.core.io.Resource; |
||||||
|
|
||||||
|
/** |
||||||
|
* A factory that creates a data source fit for use in a system environment. Creates a DBCP simple data source |
||||||
|
* from the provided connection properties. |
||||||
|
* |
||||||
|
* This factory returns a fully-initialized DataSource implementation. When the DataSource is returned, callers are |
||||||
|
* guaranteed that the database schema and data will have been loaded by that time. |
||||||
|
* |
||||||
|
* Is a FactoryBean, for exposing the fully-initialized DataSource as a Spring bean. See {@link #getObject()}. |
||||||
|
* |
||||||
|
* @author Chris Beams |
||||||
|
* @author Scott Andrews |
||||||
|
*/ |
||||||
|
public class DbcpDataSourceFactory implements FactoryBean<DataSource>, DisposableBean { |
||||||
|
|
||||||
|
// configurable properties
|
||||||
|
|
||||||
|
private String driverClassName; |
||||||
|
|
||||||
|
private String url; |
||||||
|
|
||||||
|
private String username; |
||||||
|
|
||||||
|
private String password; |
||||||
|
|
||||||
|
private boolean populate; |
||||||
|
|
||||||
|
private Resource schemaLocation; |
||||||
|
|
||||||
|
private Resource dataLocation; |
||||||
|
|
||||||
|
/** |
||||||
|
* The object created by this factory. |
||||||
|
*/ |
||||||
|
private BasicDataSource dataSource; |
||||||
|
|
||||||
|
public void setDriverClassName(String driverClassName) { |
||||||
|
this.driverClassName = driverClassName; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The data source connection URL |
||||||
|
*/ |
||||||
|
public void setUrl(String url) { |
||||||
|
this.url = url; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The data source username |
||||||
|
*/ |
||||||
|
public void setUsername(String username) { |
||||||
|
this.username = username; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
*The data source password |
||||||
|
*/ |
||||||
|
public void setPassword(String password) { |
||||||
|
this.password = password; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Indicates that the data base should be populated from the schema and data locations |
||||||
|
*/ |
||||||
|
public void setPopulate(boolean populate) { |
||||||
|
this.populate = populate; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the location of the file containing the schema DDL to export to the database. |
||||||
|
* @param schemaLocation the location of the database schema DDL |
||||||
|
*/ |
||||||
|
public void setSchemaLocation(Resource schemaLocation) { |
||||||
|
this.schemaLocation = schemaLocation; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the location of the file containing the data to load into the database. |
||||||
|
* @param testDataLocation the location of the data file |
||||||
|
*/ |
||||||
|
public void setDataLocation(Resource testDataLocation) { |
||||||
|
this.dataLocation = testDataLocation; |
||||||
|
} |
||||||
|
|
||||||
|
// implementing FactoryBean
|
||||||
|
|
||||||
|
// this method is called by Spring to expose the DataSource as a bean
|
||||||
|
public DataSource getObject() throws Exception { |
||||||
|
if (dataSource == null) { |
||||||
|
initDataSource(); |
||||||
|
} |
||||||
|
return dataSource; |
||||||
|
} |
||||||
|
|
||||||
|
public Class<DataSource> getObjectType() { |
||||||
|
return DataSource.class; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isSingleton() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
// implementing DisposableBean
|
||||||
|
|
||||||
|
public void destroy() throws Exception { |
||||||
|
dataSource.close(); |
||||||
|
} |
||||||
|
|
||||||
|
// internal helper methods
|
||||||
|
|
||||||
|
// encapsulates the steps involved in initializing the data source: creating it, and populating it
|
||||||
|
private void initDataSource() { |
||||||
|
// create the database source first
|
||||||
|
this.dataSource = createDataSource(); |
||||||
|
|
||||||
|
if (this.populate) { |
||||||
|
// now populate the database by loading the schema and data
|
||||||
|
populateDataSource(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private BasicDataSource createDataSource() { |
||||||
|
BasicDataSource dataSource = new BasicDataSource(); |
||||||
|
dataSource.setDriverClassName(this.driverClassName); |
||||||
|
dataSource.setUrl(this.url); |
||||||
|
dataSource.setUsername(this.username); |
||||||
|
dataSource.setPassword(this.password); |
||||||
|
return dataSource; |
||||||
|
} |
||||||
|
|
||||||
|
private void populateDataSource() { |
||||||
|
DatabasePopulator populator = new DatabasePopulator(dataSource); |
||||||
|
populator.populate(this.schemaLocation); |
||||||
|
populator.populate(this.dataLocation); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Populates a in memory data source with data. |
||||||
|
*/ |
||||||
|
private class DatabasePopulator { |
||||||
|
|
||||||
|
private DataSource dataSource; |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a new database populator. |
||||||
|
* @param dataSource the data source that will be populated. |
||||||
|
*/ |
||||||
|
public DatabasePopulator(DataSource dataSource) { |
||||||
|
this.dataSource = dataSource; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Populate the database executing the statements in the provided resource against the database |
||||||
|
* @param sqlFile spring resource containing SQL to run against the db |
||||||
|
*/ |
||||||
|
public void populate(Resource sqlFile) { |
||||||
|
Connection connection = null; |
||||||
|
try { |
||||||
|
connection = dataSource.getConnection(); |
||||||
|
try { |
||||||
|
String sql = parseSqlIn(sqlFile); |
||||||
|
executeSql(sql, connection); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new RuntimeException("I/O exception occurred accessing the database schema file", e); |
||||||
|
} catch (SQLException e) { |
||||||
|
throw new RuntimeException("SQL exception occurred exporting database schema", e); |
||||||
|
} |
||||||
|
} catch (SQLException e) { |
||||||
|
throw new RuntimeException("SQL exception occurred acquiring connection", e); |
||||||
|
} finally { |
||||||
|
if (connection != null) { |
||||||
|
try { |
||||||
|
connection.close(); |
||||||
|
} catch (SQLException e) { |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// utility method to read a .sql txt input stream
|
||||||
|
private String parseSqlIn(Resource resource) throws IOException { |
||||||
|
InputStream is = null; |
||||||
|
try { |
||||||
|
is = resource.getInputStream(); |
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); |
||||||
|
|
||||||
|
StringWriter sw = new StringWriter(); |
||||||
|
BufferedWriter writer = new BufferedWriter(sw); |
||||||
|
|
||||||
|
for (int c=reader.read(); c != -1; c=reader.read()) { |
||||||
|
writer.write(c); |
||||||
|
} |
||||||
|
writer.flush(); |
||||||
|
return sw.toString(); |
||||||
|
|
||||||
|
} finally { |
||||||
|
if (is != null) { |
||||||
|
is.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// utility method to run the parsed sql
|
||||||
|
private void executeSql(String sql, Connection connection) throws SQLException { |
||||||
|
Statement statement = connection.createStatement(); |
||||||
|
statement.execute(sql); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,55 @@ |
|||||||
|
CREATE TABLE vets ( |
||||||
|
id INTEGER NOT NULL IDENTITY PRIMARY KEY, |
||||||
|
first_name VARCHAR(30), |
||||||
|
last_name VARCHAR(30) |
||||||
|
); |
||||||
|
CREATE INDEX vets_last_name ON vets(last_name); |
||||||
|
|
||||||
|
CREATE TABLE specialties ( |
||||||
|
id INTEGER NOT NULL IDENTITY PRIMARY KEY, |
||||||
|
name VARCHAR(80) |
||||||
|
); |
||||||
|
CREATE INDEX specialties_name ON specialties(name); |
||||||
|
|
||||||
|
CREATE TABLE vet_specialties ( |
||||||
|
vet_id INTEGER NOT NULL, |
||||||
|
specialty_id INTEGER NOT NULL |
||||||
|
); |
||||||
|
alter table vet_specialties add constraint fk_vet_specialties_vets foreign key (vet_id) references vets(id); |
||||||
|
alter table vet_specialties add constraint fk_vet_specialties_specialties foreign key (specialty_id) references specialties(id); |
||||||
|
|
||||||
|
CREATE TABLE types ( |
||||||
|
id INTEGER NOT NULL IDENTITY PRIMARY KEY, |
||||||
|
name VARCHAR(80) |
||||||
|
); |
||||||
|
CREATE INDEX types_name ON types(name); |
||||||
|
|
||||||
|
CREATE TABLE owners ( |
||||||
|
id INTEGER NOT NULL IDENTITY PRIMARY KEY, |
||||||
|
first_name VARCHAR(30), |
||||||
|
last_name VARCHAR(30), |
||||||
|
address VARCHAR(255), |
||||||
|
city VARCHAR(80), |
||||||
|
telephone VARCHAR(20) |
||||||
|
); |
||||||
|
CREATE INDEX owners_last_name ON owners(last_name); |
||||||
|
|
||||||
|
CREATE TABLE pets ( |
||||||
|
id INTEGER NOT NULL IDENTITY PRIMARY KEY, |
||||||
|
name VARCHAR(30), |
||||||
|
birth_date DATE, |
||||||
|
type_id INTEGER NOT NULL, |
||||||
|
owner_id INTEGER NOT NULL |
||||||
|
); |
||||||
|
alter table pets add constraint fk_pets_owners foreign key (owner_id) references owners(id); |
||||||
|
alter table pets add constraint fk_pets_types foreign key (type_id) references types(id); |
||||||
|
CREATE INDEX pets_name ON pets(name); |
||||||
|
|
||||||
|
CREATE TABLE visits ( |
||||||
|
id INTEGER NOT NULL IDENTITY PRIMARY KEY, |
||||||
|
pet_id INTEGER NOT NULL, |
||||||
|
visit_date DATE, |
||||||
|
description VARCHAR(255) |
||||||
|
); |
||||||
|
alter table visits add constraint fk_visits_pets foreign key (pet_id) references pets(id); |
||||||
|
CREATE INDEX visits_pet_id ON visits(pet_id); |
||||||
@ -0,0 +1,53 @@ |
|||||||
|
INSERT INTO vets VALUES (1, 'James', 'Carter'); |
||||||
|
INSERT INTO vets VALUES (2, 'Helen', 'Leary'); |
||||||
|
INSERT INTO vets VALUES (3, 'Linda', 'Douglas'); |
||||||
|
INSERT INTO vets VALUES (4, 'Rafael', 'Ortega'); |
||||||
|
INSERT INTO vets VALUES (5, 'Henry', 'Stevens'); |
||||||
|
INSERT INTO vets VALUES (6, 'Sharon', 'Jenkins'); |
||||||
|
|
||||||
|
INSERT INTO specialties VALUES (1, 'radiology'); |
||||||
|
INSERT INTO specialties VALUES (2, 'surgery'); |
||||||
|
INSERT INTO specialties VALUES (3, 'dentistry'); |
||||||
|
|
||||||
|
INSERT INTO vet_specialties VALUES (2, 1); |
||||||
|
INSERT INTO vet_specialties VALUES (3, 2); |
||||||
|
INSERT INTO vet_specialties VALUES (3, 3); |
||||||
|
INSERT INTO vet_specialties VALUES (4, 2); |
||||||
|
INSERT INTO vet_specialties VALUES (5, 1); |
||||||
|
|
||||||
|
INSERT INTO types VALUES (1, 'cat'); |
||||||
|
INSERT INTO types VALUES (2, 'dog'); |
||||||
|
INSERT INTO types VALUES (3, 'lizard'); |
||||||
|
INSERT INTO types VALUES (4, 'snake'); |
||||||
|
INSERT INTO types VALUES (5, 'bird'); |
||||||
|
INSERT INTO types VALUES (6, 'hamster'); |
||||||
|
|
||||||
|
INSERT INTO owners VALUES (1, 'George', 'Franklin', '110 W. Liberty St.', 'Madison', '6085551023'); |
||||||
|
INSERT INTO owners VALUES (2, 'Betty', 'Davis', '638 Cardinal Ave.', 'Sun Prairie', '6085551749'); |
||||||
|
INSERT INTO owners VALUES (3, 'Eduardo', 'Rodriquez', '2693 Commerce St.', 'McFarland', '6085558763'); |
||||||
|
INSERT INTO owners VALUES (4, 'Harold', 'Davis', '563 Friendly St.', 'Windsor', '6085553198'); |
||||||
|
INSERT INTO owners VALUES (5, 'Peter', 'McTavish', '2387 S. Fair Way', 'Madison', '6085552765'); |
||||||
|
INSERT INTO owners VALUES (6, 'Jean', 'Coleman', '105 N. Lake St.', 'Monona', '6085552654'); |
||||||
|
INSERT INTO owners VALUES (7, 'Jeff', 'Black', '1450 Oak Blvd.', 'Monona', '6085555387'); |
||||||
|
INSERT INTO owners VALUES (8, 'Maria', 'Escobito', '345 Maple St.', 'Madison', '6085557683'); |
||||||
|
INSERT INTO owners VALUES (9, 'David', 'Schroeder', '2749 Blackhawk Trail', 'Madison', '6085559435'); |
||||||
|
INSERT INTO owners VALUES (10, 'Carlos', 'Estaban', '2335 Independence La.', 'Waunakee', '6085555487'); |
||||||
|
|
||||||
|
INSERT INTO pets VALUES (1, 'Leo', '2000-09-07', 1, 1); |
||||||
|
INSERT INTO pets VALUES (2, 'Basil', '2002-08-06', 6, 2); |
||||||
|
INSERT INTO pets VALUES (3, 'Rosy', '2001-04-17', 2, 3); |
||||||
|
INSERT INTO pets VALUES (4, 'Jewel', '2000-03-07', 2, 3); |
||||||
|
INSERT INTO pets VALUES (5, 'Iggy', '2000-11-30', 3, 4); |
||||||
|
INSERT INTO pets VALUES (6, 'George', '2000-01-20', 4, 5); |
||||||
|
INSERT INTO pets VALUES (7, 'Samantha', '1995-09-04', 1, 6); |
||||||
|
INSERT INTO pets VALUES (8, 'Max', '1995-09-04', 1, 6); |
||||||
|
INSERT INTO pets VALUES (9, 'Lucky', '1999-08-06', 5, 7); |
||||||
|
INSERT INTO pets VALUES (10, 'Mulligan', '1997-02-24', 2, 8); |
||||||
|
INSERT INTO pets VALUES (11, 'Freddy', '2000-03-09', 5, 9); |
||||||
|
INSERT INTO pets VALUES (12, 'Lucky', '2000-06-24', 2, 10); |
||||||
|
INSERT INTO pets VALUES (13, 'Sly', '2002-06-08', 1, 10); |
||||||
|
|
||||||
|
INSERT INTO visits VALUES (1, 7, '1996-03-04', 'rabies shot'); |
||||||
|
INSERT INTO visits VALUES (2, 8, '1996-03-04', 'rabies shot'); |
||||||
|
INSERT INTO visits VALUES (3, 8, '1996-06-04', 'neutered'); |
||||||
|
INSERT INTO visits VALUES (4, 7, '1996-09-04', 'spayed'); |
||||||
Loading…
Reference in new issue