/* * 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.id; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.persistence.GenerationType; import org.seasar.extension.jdbc.EntityMeta; import org.seasar.extension.jdbc.JdbcContext; import org.seasar.extension.jdbc.PropertyMeta; import org.seasar.extension.jdbc.SqlLogger; import org.seasar.extension.jdbc.exception.IdGenerationFailedRuntimeException; import org.seasar.extension.jdbc.manager.JdbcManagerImplementor; import org.seasar.framework.util.PreparedStatementUtil; import org.seasar.framework.util.StringUtil; /** * {@link GenerationType#IDENTITY}方式で識別子の値を自動生成するIDジェネレータです。 * * @author koichik */ public class IdentityIdGenerator extends AbstractIdGenerator { /** * インスタンスを構築します。 * * @param entityMeta * エンティティのメタデータ * @param propertyMeta * 識別子を表すプロパティのメタデータ */ public IdentityIdGenerator(final EntityMeta entityMeta, final PropertyMeta propertyMeta) { super(entityMeta, propertyMeta); } public boolean supportBatch(final JdbcManagerImplementor jdbcManager) { return false; } public boolean useGetGeneratedKeys(final JdbcManagerImplementor jdbcManager) { return jdbcManager.getDialect().supportsGetGeneratedKeys(); } public boolean isInsertInto(final JdbcManagerImplementor jdbcManager) { return jdbcManager.getDialect().isInsertIdentityColumn(); } public Object preInsert(final JdbcManagerImplementor jdbcManager, final Object entity, final SqlLogger sqlLogger) { return null; } public void postInsert(final JdbcManagerImplementor jdbcManager, final Object entity, final Statement statement, final SqlLogger sqlLogger) { final long id; if (jdbcManager.getDialect().supportsGetGeneratedKeys()) { id = getGeneratedId(statement); } else { id = getGeneratedId(jdbcManager, sqlLogger); } setId(entity, id); } /** * {@link Statement#getGeneratedKeys()}を使用して自動生成された識別子の値を取得して返します。 * * @param statement * INSERT文を実行した{@link Statement} * @return 自動生成された識別子の値 */ protected long getGeneratedId(final Statement statement) { try { final ResultSet rs = statement.getGeneratedKeys(); return getGeneratedId(rs); } catch (final SQLException e) { throw new IdGenerationFailedRuntimeException(entityMeta.getName(), propertyMeta.getName(), e); } } /** * DBMS固有のSQLを使用して自動生成された識別子の値を取得して返します。 * * @param jdbcManager * 内部的なJDBCマネージャ * @param sqlLogger * SQLロガー * @return 自動生成された識別子の値 */ protected long getGeneratedId(final JdbcManagerImplementor jdbcManager, final SqlLogger sqlLogger) { final String sql = jdbcManager.getDialect().getIdentitySelectString( toQualifiedName(entityMeta.getTableMeta().getSchema(), entityMeta.getTableMeta().getName()), propertyMeta.getColumnMeta().getName()); sqlLogger.logSql(sql); final JdbcContext jdbcContext = jdbcManager.getJdbcContext(); try { final PreparedStatement ps = jdbcContext.getPreparedStatement(sql); final ResultSet rs = PreparedStatementUtil.executeQuery(ps); return getGeneratedId(rs); } finally { if (!jdbcContext.isTransactional()) { jdbcContext.destroy(); } } } /** * スキーマ名が指定された場合は修飾された名前を返します。 * * @param schema * スキーマ名 * @param tableName * テーブル名 * @return 修飾された名前 */ protected String toQualifiedName(String schema, String tableName) { if (StringUtil.isEmpty(schema)) { return tableName; } return schema + "." + tableName; } }