private ValueGeneration determineValueGenerationStrategy(XProperty property) { ValueGeneration valueGeneration = getValueGenerationFromAnnotations( property ); if ( valueGeneration == null ) { return NoValueGeneration.INSTANCE; } final GenerationTiming when = valueGeneration.getGenerationTiming(); if ( valueGeneration.getValueGenerator() == null ) { insertable = false; if ( when == GenerationTiming.ALWAYS ) { updatable = false; } } return valueGeneration; }
public GenerationStrategyPair( InMemoryValueGenerationStrategy inMemoryStrategy, InDatabaseValueGenerationStrategy inDatabaseStrategy) { // perform some normalization. Also check that only one (if any) strategy is specified if ( inMemoryStrategy == null ) { inMemoryStrategy = NoInMemoryValueGenerationStrategy.INSTANCE; } if ( inDatabaseStrategy == null ) { inDatabaseStrategy = NoInDatabaseValueGenerationStrategy.INSTANCE; } if ( inMemoryStrategy.getGenerationTiming() != GenerationTiming.NEVER && inDatabaseStrategy.getGenerationTiming() != GenerationTiming.NEVER ) { throw new ValueGenerationStrategyException( "in-memory and in-database value generation are mutually exclusive" ); } this.inMemoryStrategy = inMemoryStrategy; this.inDatabaseStrategy = inDatabaseStrategy; }
private static void bindVersioningProperty(Table table, Element subnode, Mappings mappings, String name, RootClass entity, java.util.Map inheritedMetas) { String propertyName = subnode.attributeValue( "name" ); SimpleValue val = new SimpleValue( mappings, table ); bindSimpleValue( subnode, val, false, propertyName, mappings ); if ( !val.isTypeSpecified() ) { // this is either a <version/> tag with no type attribute, // or a <timestamp/> tag if ( "version".equals( name ) ) { val.setTypeName( "integer" ); } else { if ( "db".equals( subnode.attributeValue( "source" ) ) ) { val.setTypeName( "dbtimestamp" ); } else { val.setTypeName( "timestamp" ); } } } Property prop = new Property(); prop.setValue( val ); bindProperty( subnode, prop, mappings, inheritedMetas ); // for version properties marked as being generated, make sure they are "always" // generated; aka, "insert" is invalid; this is dis-allowed by the DTD, // but just to make sure... if ( prop.getValueGenerationStrategy() != null ) { if ( prop.getValueGenerationStrategy().getGenerationTiming() == GenerationTiming.INSERT ) { throw new MappingException( "'generated' attribute cannot be 'insert' for versioning property" ); } } makeVersion( subnode, val ); entity.setVersion( prop ); entity.addProperty( prop ); }
/** * In case the given annotation is a value generator annotation, the corresponding value generation strategy to be * applied to the given property is returned, {@code null} otherwise. */ private <A extends Annotation> AnnotationValueGeneration<A> getValueGenerationFromAnnotation( XProperty property, A annotation) { ValueGenerationType generatorAnnotation = annotation.annotationType() .getAnnotation( ValueGenerationType.class ); if ( generatorAnnotation == null ) { return null; } Class<? extends AnnotationValueGeneration<?>> generationType = generatorAnnotation.generatedBy(); AnnotationValueGeneration<A> valueGeneration = instantiateAndInitializeValueGeneration( annotation, generationType, property ); if ( annotation.annotationType() == Generated.class && property.isAnnotationPresent( javax.persistence.Version.class ) && valueGeneration.getGenerationTiming() == GenerationTiming.INSERT ) { throw new AnnotationException( "@Generated(INSERT) on a @Version property not allowed, use ALWAYS (or NEVER): " + StringHelper.qualify( holder.getPath(), name ) ); } return valueGeneration; }
private static GenerationStrategyPair buildGenerationStrategyPair( final SessionFactoryImplementor sessionFactory, final Property mappingProperty) { final ValueGeneration valueGeneration = mappingProperty.getValueGenerationStrategy(); if ( valueGeneration != null && valueGeneration.getGenerationTiming() != GenerationTiming.NEVER ) { // the property is generated in full. build the generation strategy pair. if ( valueGeneration.getValueGenerator() != null ) { // in-memory generation return new GenerationStrategyPair( FullInMemoryValueGenerationStrategy.create( valueGeneration ) ); } else { // in-db generation return new GenerationStrategyPair( create( sessionFactory, mappingProperty, valueGeneration ) ); } } else if ( mappingProperty.getValue() instanceof Component ) { final CompositeGenerationStrategyPairBuilder builder = new CompositeGenerationStrategyPairBuilder( mappingProperty ); interpretPartialCompositeValueGeneration( sessionFactory, (Component) mappingProperty.getValue(), builder ); return builder.buildPair(); } return NO_GEN_PAIR; }
private void add(InMemoryValueGenerationStrategy inMemoryStrategy) { if ( inMemoryStrategies == null ) { inMemoryStrategies = new ArrayList<InMemoryValueGenerationStrategy>(); } inMemoryStrategies.add( inMemoryStrategy ); if ( inMemoryStrategy.getGenerationTiming() != GenerationTiming.NEVER ) { hadInMemoryGeneration = true; } }
private void add(InDatabaseValueGenerationStrategy inDatabaseStrategy) { if ( inDatabaseStrategies == null ) { inDatabaseStrategies = new ArrayList<InDatabaseValueGenerationStrategy>(); } inDatabaseStrategies.add( inDatabaseStrategy ); if ( inDatabaseStrategy.getGenerationTiming() != GenerationTiming.NEVER ) { hadInDatabaseGeneration = true; } }
private InDatabaseValueGenerationStrategyImpl( GenerationTiming timing, boolean referenceColumnInSql, String[] referencedColumnValues) { this.timing = timing; this.referenceColumnInSql = referenceColumnInSql; this.referencedColumnValues = referencedColumnValues; }
public boolean isNaturalIdentifierInsertGenerated() { // the intention is for this call to replace the usage of the old ValueInclusion stuff (as exposed from // persister) in SelectGenerator to determine if it is safe to use the natural identifier to find the // insert-generated identifier. That wont work if the natural-id is also insert-generated. // // Assumptions: // * That code checks that there is a natural identifier before making this call, so we assume the same here // * That code assumes a non-composite natural-id, so we assume the same here final InDatabaseValueGenerationStrategy strategy = inDatabaseValueGenerationStrategies[ naturalIdPropertyNumbers[0] ]; return strategy != null && strategy.getGenerationTiming() != GenerationTiming.NEVER; }
@Override public GenerationTiming getGenerationTiming() { return GenerationTiming.NEVER; }
protected String generateInsertGeneratedValuesSelectString() { return generateGeneratedValuesSelectString( GenerationTiming.INSERT ); }
protected String generateUpdateGeneratedValuesSelectString() { return generateGeneratedValuesSelectString( GenerationTiming.ALWAYS ); }
private String generateGeneratedValuesSelectString(final GenerationTiming generationTimingToMatch) { Select select = new Select( getFactory().getDialect() ); if ( getFactory().getSettings().isCommentsEnabled() ) { select.setComment( "get generated state " + getEntityName() ); } String[] aliasedIdColumns = StringHelper.qualify( getRootAlias(), getIdentifierColumnNames() ); // Here we render the select column list based on the properties defined as being generated. // For partial component generation, we currently just re-select the whole component // rather than trying to handle the individual generated portions. String selectClause = concretePropertySelectFragment( getRootAlias(), new InclusionChecker() { @Override public boolean includeProperty(int propertyNumber) { final InDatabaseValueGenerationStrategy generationStrategy = entityMetamodel.getInDatabaseValueGenerationStrategies()[propertyNumber]; return generationStrategy != null && timingsMatch( generationStrategy.getGenerationTiming(), generationTimingToMatch ); } } ); selectClause = selectClause.substring( 2 ); String fromClause = fromTableFragment( getRootAlias() ) + fromJoinFragment( getRootAlias(), true, false ); String whereClause = new StringBuilder() .append( StringHelper.join( "=? and ", aliasedIdColumns ) ) .append( "=?" ) .append( whereJoinFragment( getRootAlias(), true, false ) ) .toString(); return select.setSelectClause( selectClause ) .setFromClause( fromClause ) .setOuterJoins( "", "" ) .setWhereClause( whereClause ) .toStatementString(); }
public void processInsertGeneratedProperties(Serializable id, Object entity, Object[] state, SessionImplementor session) { if ( !hasInsertGeneratedProperties() ) { throw new AssertionFailure("no insert-generated properties"); } processGeneratedProperties( id, entity, state, session, sqlInsertGeneratedValuesSelectString, GenerationTiming.INSERT ); }
public void processUpdateGeneratedProperties(Serializable id, Object entity, Object[] state, SessionImplementor session) { if ( !hasUpdateGeneratedProperties() ) { throw new AssertionFailure("no update-generated properties"); } processGeneratedProperties( id, entity, state, session, sqlUpdateGeneratedValuesSelectString, GenerationTiming.ALWAYS ); }
private void processGeneratedProperties( Serializable id, Object entity, Object[] state, SessionImplementor session, String selectionSQL, GenerationTiming matchTiming) { // force immediate execution of the insert batch (if one) session.getTransactionCoordinator().getJdbcCoordinator().executeBatch(); try { PreparedStatement ps = session.getTransactionCoordinator() .getJdbcCoordinator() .getStatementPreparer() .prepareStatement( selectionSQL ); try { getIdentifierType().nullSafeSet( ps, id, 1, session ); ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( ps ); try { if ( !rs.next() ) { throw new HibernateException( "Unable to locate row for retrieval of generated properties: " + MessageHelper.infoString( this, id, getFactory() ) ); } int propertyIndex = -1; for ( NonIdentifierAttribute attribute : entityMetamodel.getProperties() ) { propertyIndex++; final ValueGeneration valueGeneration = attribute.getValueGenerationStrategy(); if ( isReadRequired( valueGeneration, matchTiming ) ) { final Object hydratedState = attribute.getType().hydrate( rs, getPropertyAliases( "", propertyIndex ), session, entity ); state[propertyIndex] = attribute.getType().resolve( hydratedState, session, entity ); setPropertyValue( entity, propertyIndex, state[propertyIndex] ); } } // for ( int i = 0; i < getPropertySpan(); i++ ) { // if ( includeds[i] != ValueInclusion.NONE ) { // Object hydratedState = getPropertyTypes()[i].hydrate( rs, getPropertyAliases( "", i ), session, entity ); // state[i] = getPropertyTypes()[i].resolve( hydratedState, session, entity ); // setPropertyValue( entity, i, state[i] ); // } // } } finally { if ( rs != null ) { session.getTransactionCoordinator().getJdbcCoordinator().release( rs, ps ); } } } finally { session.getTransactionCoordinator().getJdbcCoordinator().release( ps ); } } catch( SQLException e ) { throw getFactory().getSQLExceptionHelper().convert( e, "unable to select generated column values", selectionSQL ); } }
/** * Whether the given value generation strategy requires to read the value from the database or not. */ private boolean isReadRequired(ValueGeneration valueGeneration, GenerationTiming matchTiming) { return valueGeneration != null && valueGeneration.getValueGenerator() == null && timingsMatch( valueGeneration.getGenerationTiming(), matchTiming ); }
private boolean timingsMatch(GenerationTiming timing, GenerationTiming matchTiming) { return (matchTiming == GenerationTiming.INSERT && timing.includesInsert()) || (matchTiming == GenerationTiming.ALWAYS && timing.includesUpdate()); }
public GenerationStrategyPair buildPair() { if ( hadInMemoryGeneration && hadInDatabaseGeneration ) { throw new ValueGenerationStrategyException( "Composite attribute [" + mappingProperty.getName() + "] contained both in-memory" + " and in-database value generation" ); } else if ( hadInMemoryGeneration ) { throw new NotYetImplementedException( "Still need to wire in composite in-memory value generation" ); } else if ( hadInDatabaseGeneration ) { final Component composite = (Component) mappingProperty.getValue(); // we need the numbers to match up so we can properly handle 'referenced sql column values' if ( inDatabaseStrategies.size() != composite.getPropertySpan() ) { throw new ValueGenerationStrategyException( "Internal error : mismatch between number of collected in-db generation strategies" + " and number of attributes for composite attribute : " + mappingProperty.getName() ); } // the base-line values for the aggregated InDatabaseValueGenerationStrategy we will build here. GenerationTiming timing = GenerationTiming.INSERT; boolean referenceColumns = false; String[] columnValues = new String[ composite.getColumnSpan() ]; // start building the aggregate values int propertyIndex = -1; int columnIndex = 0; Iterator subProperties = composite.getPropertyIterator(); while ( subProperties.hasNext() ) { propertyIndex++; final Property subProperty = (Property) subProperties.next(); final InDatabaseValueGenerationStrategy subStrategy = inDatabaseStrategies.get( propertyIndex ); if ( subStrategy.getGenerationTiming() == GenerationTiming.ALWAYS ) { // override the base-line to the more often "ALWAYS"... timing = GenerationTiming.ALWAYS; } if ( subStrategy.referenceColumnsInSql() ) { // override base-line value referenceColumns = true; } if ( subStrategy.getReferencedColumnValues() != null ) { if ( subStrategy.getReferencedColumnValues().length != subProperty.getColumnSpan() ) { throw new ValueGenerationStrategyException( "Internal error : mismatch between number of collected 'referenced column values'" + " and number of columns for composite attribute : " + mappingProperty.getName() + '.' + subProperty.getName() ); } System.arraycopy( subStrategy.getReferencedColumnValues(), 0, columnValues, columnIndex, subProperty.getColumnSpan() ); } } // then use the aggregated values to build the InDatabaseValueGenerationStrategy return new GenerationStrategyPair( new InDatabaseValueGenerationStrategyImpl( timing, referenceColumns, columnValues ) ); } else { return NO_GEN_PAIR; } }
private FullInMemoryValueGenerationStrategy(GenerationTiming timing, ValueGenerator generator) { this.timing = timing; this.generator = generator; }
@Override public GenerationTiming getGenerationTiming() { return timing; }
private boolean isInsertGenerated(NonIdentifierAttribute property) { return property.getValueGenerationStrategy() != null && property.getValueGenerationStrategy().getGenerationTiming() != GenerationTiming.NEVER; }
private boolean isInsertGenerated(Property property) { return property.getValueGenerationStrategy() != null && property.getValueGenerationStrategy().getGenerationTiming() != GenerationTiming.NEVER; }
private static boolean isUpdateGenerated(Property property) { return property.getValueGenerationStrategy() != null && property.getValueGenerationStrategy().getGenerationTiming() == GenerationTiming.ALWAYS; }
private static boolean isUpdateGenerated(NonIdentifierAttribute property) { return property.getValueGenerationStrategy() != null && property.getValueGenerationStrategy().getGenerationTiming() == GenerationTiming.ALWAYS; }
public boolean isVersionGenerated() { final InDatabaseValueGenerationStrategy strategy = inDatabaseValueGenerationStrategies[ versionPropertyIndex ]; return strategy != null && strategy.getGenerationTiming() != GenerationTiming.NEVER; }
public GenerationTiming getGenerationTiming() { return GenerationTiming.ALWAYS; }