View Javadoc

1   /*
2    * Copyright 2004-2006 the Seasar Foundation and the Others.
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, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.tuigwaa.database;
17  
18  import java.sql.Connection;
19  import java.sql.PreparedStatement;
20  import java.sql.SQLException;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.hibernate.HibernateException;
30  import org.hibernate.cfg.Configuration;
31  import org.hibernate.dialect.Dialect;
32  import org.hibernate.mapping.ForeignKey;
33  import org.hibernate.mapping.Table;
34  import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
35  import org.seasar.tuigwaa.model.core.TgwEntity;
36  import org.seasar.tuigwaa.util.TgwUtils;
37  
38  import com.isenshi.util.TableMap;
39  
40  /***
41   * @author nishioka
42   */
43  public class DynaDatabaseServiceImpl implements DynaDatabaseService {
44  
45  	private Log log = LogFactory.getLog(getClass());
46  
47  	private BasicDatabaseService db;
48  
49  	private DynaSessionFactory factory_;
50  
51  	private TableMap tableNameMap = new TableMap();
52  
53  	public DynaDatabaseServiceImpl(BasicDatabaseService basicDBService,
54  			DynaSessionFactory factory) {
55  		this.db = basicDBService;
56  		this.factory_ = factory;
57  	}
58  
59  	public void createSchema(String domainName) throws Exception {
60  		if (db.useBaseDatabase(domainName) && !db.existSchema(domainName)) {
61  			DynaConfiguration cfg = factory_.getConfiguration(domainName);
62  			String sql = cfg.getCreateSchemaSQLString(domainName);
63  			executeSQL(domainName, sql);
64  		}
65  	}
66  
67  	public void dropSchema(String domainName) throws Exception {
68  		if (db.useBaseDatabase(domainName) && db.existSchema(domainName)) {
69  			DynaConfiguration cfg = factory_.getConfiguration(domainName);
70  			String sql = cfg.getDropSchemaSQLString(domainName);
71  			executeSQL(domainName, sql);
72  		}else{
73  			db.removeExternalDatabaseMapping(domainName);
74  		}
75  		factory_.deleteConfiguration(domainName);
76  	}
77  
78  	public void createTable(TgwEntity entity) {
79  		String domainName = entity.getDomainName();
80  		DynaConfiguration cfg = factory_.getConfiguration(domainName);
81  
82  		try {
83  			// change configuration
84  			Table table = addTable(cfg, domainName, entity, true);
85  
86  			// change physical database
87  			if (!existTable(entity)) {
88  				doCreateTable(cfg, domainName, table);
89  				doCreateForeignKey(cfg, domainName, table);
90  			}
91  		} catch (SQLException e) {
92  			e.printStackTrace();
93  			throw new RuntimeException(e);
94  		} catch (HibernateException e) {
95  			e.printStackTrace();
96  			throw new RuntimeException(e);
97  		} catch (ClassNotFoundException e) {
98  			e.printStackTrace();
99  			throw new RuntimeException(e);
100 		}
101 	}
102 
103 	public void createTables(String domainName, Collection entityList) {
104 		DynaConfiguration cfg = factory_.getConfiguration(domainName);
105 		List tableList = new ArrayList();
106 		try {
107 			// change configuration
108 			Iterator itr = entityList.iterator();
109 			while (itr.hasNext()) {
110 				TgwEntity entity = (TgwEntity) itr.next();
111 				Table table = addTable(cfg, domainName, entity, false);
112 				if (!existTable(entity)) {
113 					tableList.add(table);
114 				}
115 			}
116 			cfg.build();
117 
118 			// change physical database
119 			itr = tableList.iterator();
120 			while (itr.hasNext()) {
121 				Table table = (Table) itr.next();
122 				doCreateTable(cfg, domainName, table);
123 				doCreateForeignKey(cfg, domainName, table);
124 			}
125 		} catch (HibernateException e) {
126 			e.printStackTrace();
127 		} catch (ClassNotFoundException e) {
128 			e.printStackTrace();
129 		} catch (SQLException e) {
130 			e.printStackTrace();
131 		}
132 	}
133 
134 	public List readTables(String domainName) {
135 		List list = new ArrayList();
136 		try {
137 			Map map = db.createEntityMap(domainName);
138 			list.addAll(map.values());
139 		} catch (SQLException e) {
140 			// TODO
141 			log.info("Can't read database");
142 		}
143 		return list;
144 	}
145 
146 	public void alterTable(TgwEntity entity) throws Exception {
147 		String domainName = entity.getDomainName();
148 
149 		DynaConfiguration cfg = factory_.getConfiguration(domainName);
150 
151 		String schema = db.getSchemaName(domainName);
152 
153 		// change configuration
154 		Table table = cfg.alterTable(schema, entity);
155 
156 		// Physical Database Manipulate
157 		DatabaseMetadata metadata = getDatabaseMetadata(domainName);
158 
159 		Iterator itr = cfg.getAlterSQLString(table, metadata, schema);
160 		while (itr.hasNext()) {
161 			String sql = (String) itr.next();
162 			executeSQL(domainName, sql);
163 		}
164 	}
165 
166 	public void dropTable(String domainName, String entityName)
167 			throws Exception {
168 		DynaConfiguration cfg = factory_.getConfiguration(domainName);
169 
170 		if (db.useBaseDatabase(domainName)) {
171 			String schema = db.getSchemaName(domainName);
172 			cfg.deleteTable(schema, entityName);
173 			doDropTable(cfg, domainName, schema, entityName);
174 		}
175 	}
176 
177 	public void dropTables(String domainName, String[] entityNames)
178 			throws Exception {
179 		DynaConfiguration cfg = factory_.getConfiguration(domainName);
180 		if (db.useBaseDatabase(domainName)) {
181 			String schema = db.getSchemaName(domainName);
182 			cfg.deleteTable(schema, entityNames);
183 			for (int i = 0; i < entityNames.length; i++) {
184 				doDropTable(cfg, domainName, schema, entityNames[i]);
185 			}
186 		}
187 	}
188 
189 	// [Start] ----- Private Method -----
190 
191 	private void executeSQL(String domainName, String sql) throws SQLException,
192 			HibernateException {
193 		Connection conn = db.getConnection(domainName);
194 		PreparedStatement stmt = conn.prepareStatement(sql);
195 		log.info("execute SQL: " + sql);
196 		stmt.executeUpdate();
197 	}
198 
199 	private DatabaseMetadata getDatabaseMetadata(String domainName)
200 			throws SQLException {
201 		Connection conn = db.getConnection(domainName);
202 		Configuration cfg = factory_.getConfiguration(domainName);
203 		Dialect dialect = Dialect.getDialect(cfg.getProperties());
204 		DatabaseMetadata metadata = new DatabaseMetadata(conn, dialect);
205 		return metadata;
206 	}
207 
208 	private void doCreateTable(DynaConfiguration cfg, String domainName,
209 			Table table) throws HibernateException, SQLException {
210 		String sql = cfg.getCreateSQLString(table);
211 		executeSQL(domainName, sql);
212 	}
213 
214 	private boolean existTable(TgwEntity entity) {
215 		String domainName = entity.getDomainName();
216 		String tableName = TgwUtils.toTableName(entity);
217 		return db.existTable(domainName, tableName);
218 	}
219 
220 	private void doCreateForeignKey(DynaConfiguration cfg, String schema,
221 			Table table) throws HibernateException, SQLException {
222 		Iterator fks = table.getForeignKeyIterator();
223 		while (fks.hasNext()) {
224 			ForeignKey fk = (ForeignKey) fks.next();
225 			executeSQL(schema, cfg.getForeignKeySQLString(fk));
226 		}
227 	}
228 
229 	private void doDropTable(DynaConfiguration cfg, String domainName,
230 			String schema, String entityName) throws HibernateException,
231 			SQLException {
232 		Table table = new Table();
233 		if (schema != null) {
234 			table.setSchema(schema);
235 		}
236 
237 		String tableName = (String) tableNameMap.get(domainName, entityName);
238 		if (tableName != null) {
239 			table.setName(tableName);
240 			String sql = cfg.getDropSQLString(table);
241 			executeSQL(domainName, sql);
242 		}
243 	}
244 
245 	private Table addTable(DynaConfiguration cfg, String domainName,
246 			TgwEntity entity, boolean needRebuild) throws HibernateException,
247 			ClassNotFoundException {
248 		String tableName = TgwUtils.toTableName(entity);
249 		String schema = db.getSchemaName(domainName);
250 
251 		tableNameMap.put(tableName, domainName, entity.getName());
252 		return cfg.addTable(schema, entity, needRebuild);
253 	}
254 }