/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Middleware LLC.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 *
 */
package org.hibernate.id;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.insert.AbstractSelectingDelegate;
import org.hibernate.id.insert.IdentifierGeneratingInsert;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.type.Type;

A generator that selects the just inserted row to determine the identifier value assigned by the database. The correct row is located using a unique key.

One mapping parameter is required: key (unless a natural-id is defined in the mapping).
Author:Gavin King
/** * A generator that selects the just inserted row to determine the identifier * value assigned by the database. The correct row is located using a unique * key. * <p/> * One mapping parameter is required: key (unless a natural-id is defined in the mapping). * * @author Gavin King */
public class SelectGenerator extends AbstractPostInsertGenerator implements Configurable { private String uniqueKeyPropertyName; public void configure(Type type, Properties params, Dialect d) throws MappingException { uniqueKeyPropertyName = params.getProperty( "key" ); } public InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate( PostInsertIdentityPersister persister, Dialect dialect, boolean isGetGeneratedKeysEnabled) throws HibernateException { return new SelectGeneratorDelegate( persister, dialect, uniqueKeyPropertyName ); } private static String determineNameOfPropertyToUse(PostInsertIdentityPersister persister, String supplied) { if ( supplied != null ) { return supplied; } int[] naturalIdPropertyIndices = persister.getNaturalIdentifierProperties(); if ( naturalIdPropertyIndices == null ){ throw new IdentifierGenerationException( "no natural-id property defined; need to specify [key] in " + "generator parameters" ); } if ( naturalIdPropertyIndices.length > 1 ) { throw new IdentifierGenerationException( "select generator does not currently support composite " + "natural-id properties; need to specify [key] in generator parameters" ); } if ( persister.getEntityMetamodel().isNaturalIdentifierInsertGenerated() ) { throw new IdentifierGenerationException( "natural-id also defined as insert-generated; need to specify [key] " + "in generator parameters" ); } return persister.getPropertyNames() [ naturalIdPropertyIndices[0] ]; }
The delegate for the select generation strategy.
/** * The delegate for the select generation strategy. */
public static class SelectGeneratorDelegate extends AbstractSelectingDelegate implements InsertGeneratedIdentifierDelegate { private final PostInsertIdentityPersister persister; private final Dialect dialect; private final String uniqueKeyPropertyName; private final Type uniqueKeyType; private final Type idType; private final String idSelectString; private SelectGeneratorDelegate( PostInsertIdentityPersister persister, Dialect dialect, String suppliedUniqueKeyPropertyName) { super( persister ); this.persister = persister; this.dialect = dialect; this.uniqueKeyPropertyName = determineNameOfPropertyToUse( persister, suppliedUniqueKeyPropertyName ); idSelectString = persister.getSelectByUniqueKeyString( uniqueKeyPropertyName ); uniqueKeyType = persister.getPropertyType( uniqueKeyPropertyName ); idType = persister.getIdentifierType(); } public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() { return new IdentifierGeneratingInsert( dialect ); } // AbstractSelectingDelegate impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ protected String getSelectSQL() { return idSelectString; } protected void bindParameters( SessionImplementor session, PreparedStatement ps, Object entity) throws SQLException { Object uniqueKeyValue = persister.getPropertyValue( entity, uniqueKeyPropertyName ); uniqueKeyType.nullSafeSet( ps, uniqueKeyValue, 1, session ); } protected Serializable getResult( SessionImplementor session, ResultSet rs, Object entity) throws SQLException { if ( !rs.next() ) { throw new IdentifierGenerationException( "the inserted row could not be located by the unique key: " + uniqueKeyPropertyName ); } return ( Serializable ) idType.nullSafeGet( rs, persister.getRootTableKeyColumnNames(), session, entity ); } } }