/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * 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.seasar.extension.jdbc.gen.internal.version; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import javax.sql.DataSource; import org.seasar.extension.jdbc.gen.dialect.GenDialect; import org.seasar.extension.jdbc.gen.internal.exception.NoResultRuntimeException; import org.seasar.extension.jdbc.gen.version.SchemaInfoTable; import org.seasar.extension.jdbc.util.ConnectionUtil; import org.seasar.extension.jdbc.util.DataSourceUtil; import org.seasar.framework.exception.SQLRuntimeException; import org.seasar.framework.exception.SRuntimeException; import org.seasar.framework.log.Logger; import org.seasar.framework.util.PreparedStatementUtil; import org.seasar.framework.util.ResultSetUtil; import org.seasar.framework.util.StatementUtil; /** * {@link SchemaInfoTable}の実装クラスです。 * * @author taedium */ public class SchemaInfoTableImpl implements SchemaInfoTable { /** ロガー */ protected static Logger logger = Logger .getLogger(SchemaInfoTableImpl.class); /** データソース */ protected DataSource dataSource; /** 方言 */ protected GenDialect dialect; /** カタログ名やスキーマ名を含む完全なテーブル名 */ protected String fullTableName; /** カラム名 */ protected String columnName; /** バージョンを取得するSQL */ protected String selectSql; /** テーブルを作成するSQL */ protected String createSql; /** 全データを削除するSQL */ protected String deleteSql; /** バージョンを追加するSQL */ protected String insertSql; /** * インスタンスを構築します。 * * @param dataSource * データソース * @param dialect * 方言 * @param fullTableName * カタログ名やスキーマ名を含む完全なテーブル名 * @param columnName * カラム名 */ public SchemaInfoTableImpl(DataSource dataSource, GenDialect dialect, String fullTableName, String columnName) { if (dataSource == null) { throw new NullPointerException("dataSource"); } if (dialect == null) { throw new NullPointerException("dialect"); } if (fullTableName == null) { throw new NullPointerException("fullTableName"); } if (columnName == null) { throw new NullPointerException("columnName"); } this.dataSource = dataSource; this.dialect = dialect; this.fullTableName = fullTableName; this.columnName = columnName; selectSql = createSelectSql(); insertSql = createInsertSql(); deleteSql = createDeleteSql(); createSql = createCreateSql(); } /** * バージョンを取得するSQLを作成します。 * * @return バージョンを取得するSQL */ protected String createSelectSql() { return "select " + columnName + " from " + fullTableName; } /** * バージョンを追加するSQLを作成します。 * * @return バージョンを追加するSQL */ protected String createInsertSql() { StringBuilder buf = new StringBuilder(); buf.append("insert into "); buf.append(fullTableName); buf.append(" ("); buf.append(columnName); buf.append(") values (?)"); return buf.toString(); } /** * 全データを削除するSQL * * @return 全データを削除するSQLを作成します。 */ protected String createDeleteSql() { return "delete from " + fullTableName; } /** * テーブルを作成するSQLを作成します。 * * @return テーブルを作成するSQL */ protected String createCreateSql() { StringBuilder buf = new StringBuilder(); buf.append("create table "); buf.append(fullTableName); buf.append(" ("); buf.append(columnName); buf.append(" "); buf.append(dialect.getSqlType(Types.INTEGER).getDataType(0, 10, 0, false)); buf.append(")"); return buf.toString(); } public int getVersionNo() { if (!exists()) { return 0; } return getVersionNoInternal(); } /** * 内部的にバージョン番号を返します。 * * @return バージョン番号 */ protected int getVersionNoInternal() { Connection conn = DataSourceUtil.getConnection(dataSource); try { logger.debug(selectSql); PreparedStatement ps = ConnectionUtil.prepareStatement(conn, selectSql); try { ResultSet rs = PreparedStatementUtil.executeQuery(ps); try { if (rs.next()) { return rs.getInt(1); } throw new NoResultRuntimeException(fullTableName); } catch (SQLException e) { throw new SQLRuntimeException(e); } finally { ResultSetUtil.close(rs); } } finally { StatementUtil.close(ps); } } finally { ConnectionUtil.close(conn); } } public void setVersionNo(int versionNo) { if (!exists()) { create(); } setVersionNoInternal(versionNo); } /** * 内部的にバージョン番号を設定します。 * * @param versionNo * バージョン番号 */ protected void setVersionNoInternal(int versionNo) { Connection conn = DataSourceUtil.getConnection(dataSource); try { logger.debug(deleteSql); PreparedStatement delete = ConnectionUtil.prepareStatement(conn, deleteSql); try { PreparedStatementUtil.executeUpdate(delete); } finally { StatementUtil.close(delete); } logger.debug(insertSql.replace("?", Integer.toString(versionNo))); PreparedStatement insert = ConnectionUtil.prepareStatement(conn, insertSql); try { insert.setInt(1, versionNo); PreparedStatementUtil.executeUpdate(insert); } catch (SQLException e) { throw new SQLRuntimeException(e); } finally { StatementUtil.close(insert); } } finally { ConnectionUtil.close(conn); } } /** * テーブルが存在する場合{@code true}を返します。 * * @return テーブルが存在する場合{@code true} */ protected boolean exists() { Connection conn = DataSourceUtil.getConnection(dataSource); try { logger.debug(selectSql); PreparedStatement ps = conn.prepareStatement(selectSql); try { ResultSet rs = ps.executeQuery(); try { return true; } finally { ResultSetUtil.close(rs); } } finally { StatementUtil.close(ps); } } catch (Exception e) { if (dialect.isTableNotFound(e)) { logger.log("IS2JDBCGen0004", new Object[] { fullTableName }); return false; } throw new SRuntimeException("ES2JDBCGen0027", new Object[] { e }, e); } finally { ConnectionUtil.close(conn); } } /** * テーブルを作成します。 */ protected void create() { Connection conn = DataSourceUtil.getConnection(dataSource); try { logger.debug(createSql); PreparedStatement ps = ConnectionUtil.prepareStatement(conn, createSql); try { PreparedStatementUtil.execute(ps); } finally { StatementUtil.close(ps); } } finally { ConnectionUtil.close(conn); } } }