HHH-2907 Retrofitting @Generated, making it a generator annotation type

This commit is contained in:
Gunnar Morling 2013-11-06 10:10:15 +01:00 committed by Steve Ebersole
parent cc30269b84
commit fd57a751b4
4 changed files with 96 additions and 103 deletions

View File

@ -28,14 +28,18 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.hibernate.tuple.GeneratedValueGeneration;
/**
* The annotated property is generated by the database.
*
* @author Emmanuel Bernard
*/
@ValueGenerationType( generatedBy = GeneratedValueGeneration.class )
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Generated {
/**
* The enum value representing when the value is generated.
*/

View File

@ -34,7 +34,6 @@ import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.jboss.logging.Logger;
import org.hibernate.CacheMode;
import org.hibernate.EntityMode;
import org.hibernate.FetchMode;
@ -96,6 +95,7 @@ import org.hibernate.mapping.TypeDef;
import org.hibernate.mapping.UnionSubclass;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.mapping.Value;
import org.hibernate.tuple.GeneratedValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGeneration;
import org.hibernate.tuple.ValueGenerator;
@ -1307,7 +1307,7 @@ public final class HbmBinder {
if ( generationTiming == GenerationTiming.ALWAYS || generationTiming == GenerationTiming.INSERT ) {
// we had generation specified...
// HBM only supports "database generated values"
property.setValueGenerationStrategy( new HbmDefinedValueGeneration( generationTiming ) );
property.setValueGenerationStrategy( new GeneratedValueGeneration( generationTiming ) );
// generated properties can *never* be insertable...
if ( property.isInsertable() ) {
@ -1370,37 +1370,6 @@ public final class HbmBinder {
}
private static class HbmDefinedValueGeneration implements ValueGeneration {
private final GenerationTiming timing;
private HbmDefinedValueGeneration(GenerationTiming timing) {
this.timing = timing;
}
@Override
public GenerationTiming getGenerationTiming() {
return timing;
}
@Override
public ValueGenerator getValueGenerator() {
// database generated values do not have a value generator
return null;
}
@Override
public boolean referenceColumnInSql() {
// historically these columns are not referenced in the SQL
return false;
}
@Override
public String getDatabaseGeneratedReferencedColumnValue() {
// the column is not referenced in the sql.
return null;
}
}
private static String columns(Value val) {
StringBuilder columns = new StringBuilder();
Iterator iter = val.getColumnIterator();

View File

@ -33,7 +33,6 @@ import javax.persistence.Lob;
import org.hibernate.AnnotationException;
import org.hibernate.HibernateException;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.OptimisticLock;
@ -333,50 +332,22 @@ public class PropertyBinder {
}
private ValueGeneration determineValueGenerationStrategy(XProperty property) {
ValueGeneration annotationValueGeneration = getValueGenerationFromAnnotations( property );
ValueGeneration legacyValueGeneration = getLegacyValueGeneration( property );
ValueGeneration valueGeneration = getValueGenerationFromAnnotations( property );
if ( annotationValueGeneration == null && legacyValueGeneration == null ) {
if ( valueGeneration == null ) {
return NoValueGeneration.INSTANCE;
}
else if ( annotationValueGeneration != null && legacyValueGeneration != null ) {
throw new AnnotationException(
"@Generated and a generator annotation must not be specified at the same time:" + StringHelper.qualify(
holder.getPath(),
name
)
);
}
final GenerationTiming when = annotationValueGeneration != null ?
annotationValueGeneration.getGenerationTiming() :
legacyValueGeneration.getGenerationTiming();
final GenerationTiming when = valueGeneration.getGenerationTiming();
if ( property.isAnnotationPresent( javax.persistence.Version.class ) && when == GenerationTiming.INSERT ) {
throw new AnnotationException(
"@Generated(INSERT) on a @Version property not allowed, use ALWAYS (or NEVER): "
+ StringHelper.qualify( holder.getPath(), name )
);
}
if ( legacyValueGeneration != null ) {
if ( valueGeneration.getValueGenerator() == null ) {
insertable = false;
if ( when == GenerationTiming.ALWAYS ) {
updatable = false;
}
}
return annotationValueGeneration != null ? annotationValueGeneration : legacyValueGeneration;
}
private ValueGeneration getLegacyValueGeneration(XProperty property) {
Generated generatedAnnotation = property.getAnnotation( Generated.class );
if ( generatedAnnotation != null && generatedAnnotation.value() != null && generatedAnnotation.value() != GenerationTime.NEVER ) {
return new LegacyValueGeneration( generatedAnnotation.value().getEquivalent() );
}
return null;
return valueGeneration;
}
/**
@ -421,9 +392,21 @@ public class PropertyBinder {
}
Class<? extends AnnotationValueGeneration<?>> generationType = generatorAnnotation.generatedBy();
return instantiateAndInitializeValueGeneration(
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;
}
/**
@ -470,7 +453,7 @@ public class PropertyBinder {
}
@Override
public ValueGenerator getValueGenerator() {
public ValueGenerator<?> getValueGenerator() {
return null;
}
@ -485,40 +468,6 @@ public class PropertyBinder {
}
}
private static class LegacyValueGeneration implements ValueGeneration {
private final GenerationTiming timing;
private LegacyValueGeneration(GenerationTiming timing) {
this.timing = timing;
}
@Override
public GenerationTiming getGenerationTiming() {
return timing;
}
@Override
public ValueGenerator getValueGenerator() {
// database generated values do not have a value generator
return null;
}
@Override
public boolean referenceColumnInSql() {
// historically these columns are not referenced in the SQL
return false;
}
@Override
public String getDatabaseGeneratedReferencedColumnValue() {
return null;
}
}
private boolean isCollection(Value value) {
return Collection.class.isInstance( value );
}
private boolean isToOneValue(Value value) {
return ToOne.class.isInstance( value );
}

View File

@ -0,0 +1,71 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. 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 Inc.
*
* 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.tuple;
import org.hibernate.annotations.Generated;
/**
* A {@link AnnotationValueGeneration} which marks a property as generated in the database.
*
* @author Steve Ebersole
* @author Gunnar Morling
*/
public class GeneratedValueGeneration implements AnnotationValueGeneration<Generated> {
private GenerationTiming timing;
public GeneratedValueGeneration() {
}
public GeneratedValueGeneration(GenerationTiming timing) {
this.timing = timing;
}
@Override
public void initialize(Generated annotation, Class<?> propertyType) {
this.timing = annotation.value().getEquivalent();
}
@Override
public GenerationTiming getGenerationTiming() {
return timing;
}
@Override
public ValueGenerator<?> getValueGenerator() {
// database generated values do not have a value generator
return null;
}
@Override
public boolean referenceColumnInSql() {
// historically these columns are not referenced in the SQL
return false;
}
@Override
public String getDatabaseGeneratedReferencedColumnValue() {
return null;
}
}