HHH-4527 - first cut for supporting JPA2 @Access annotation. Not quite complete and needs some more tests.

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18260 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Hardy Ferentschik 2009-12-17 21:14:07 +00:00
parent fbf7b91d4d
commit 4a9d8dcf0b
35 changed files with 2111 additions and 336 deletions

View File

@ -0,0 +1,85 @@
// $Id:$
/*
* 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.cfg;
/**
* Enum defining deifferent access strategies for accessing entity values.
*
* @author Hardy Ferentschik
*/
public enum AccessType {
/**
* Default access strategy is property
*/
DEFAULT( "property" ),
/**
* Access to value via property
*/
PROPERTY( "property" ),
/**
* Access to value via field
*/
FIELD( "field" );
private final String accessType;
AccessType(String type) {
this.accessType = type;
}
public String getType() {
return accessType;
}
public static AccessType getAccessStrategy(String type) {
if ( type == null ) {
return DEFAULT;
}
else if ( FIELD.getType().equals( type ) ) {
return FIELD;
}
else if ( PROPERTY.getType().equals( type ) ) {
return PROPERTY;
}
else {
// TODO historically if the type string could not be matched default access was used. Maybe this should be an exception though!?
return DEFAULT;
}
}
public static AccessType getAccessStrategy(javax.persistence.AccessType type) {
if ( javax.persistence.AccessType.PROPERTY.equals( type ) ) {
return PROPERTY;
}
else if ( javax.persistence.AccessType.FIELD.equals( type ) ) {
return FIELD;
}
else {
return DEFAULT;
}
}
}

View File

@ -1,3 +1,4 @@
// $Id:$
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
@ -24,8 +25,8 @@
package org.hibernate.cfg; package org.hibernate.cfg;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Arrays;
import java.util.Comparator; import java.util.Collection;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -34,6 +35,7 @@
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import javax.persistence.Access;
import javax.persistence.Basic; import javax.persistence.Basic;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorType;
@ -68,7 +70,6 @@
import javax.persistence.SqlResultSetMappings; import javax.persistence.SqlResultSetMappings;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.TableGenerator; import javax.persistence.TableGenerator;
import javax.persistence.Transient;
import javax.persistence.Version; import javax.persistence.Version;
import javax.persistence.ElementCollection; import javax.persistence.ElementCollection;
import javax.persistence.CollectionTable; import javax.persistence.CollectionTable;
@ -83,7 +84,6 @@
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.FetchMode; import org.hibernate.FetchMode;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache; import org.hibernate.annotations.Cache;
import org.hibernate.annotations.Cascade; import org.hibernate.annotations.Cascade;
@ -116,10 +116,8 @@
import org.hibernate.annotations.Parent; import org.hibernate.annotations.Parent;
import org.hibernate.annotations.Proxy; import org.hibernate.annotations.Proxy;
import org.hibernate.annotations.Sort; import org.hibernate.annotations.Sort;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.Tuplizer; import org.hibernate.annotations.Tuplizer;
import org.hibernate.annotations.Tuplizers; import org.hibernate.annotations.Tuplizers;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef; import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs; import org.hibernate.annotations.TypeDefs;
import org.hibernate.annotations.Where; import org.hibernate.annotations.Where;
@ -424,6 +422,11 @@ else if ( ann instanceof GenericGenerator ) {
/** /**
* Bind a class having JSR175 annotations * Bind a class having JSR175 annotations
* The subclasses <b>have to</b> be binded after its mother class * The subclasses <b>have to</b> be binded after its mother class
*
* @param clazzToProcess entity to bind as {@code XClass} instance
* @param inheritanceStatePerClass Meta data about the inheritance relationships for all mapped classes
* @param mappings Mapping meta data
* @throws MappingException in case there is an configuration error
*/ */
public static void bindClass( public static void bindClass(
XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass, ExtendedMappings mappings XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass, ExtendedMappings mappings
@ -621,7 +624,7 @@ else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) )
// check properties // check properties
List<PropertyData> elements = List<PropertyData> elements =
getElementsToProcess( getElementsToProcess(
persistentClass, clazzToProcess, inheritanceStatePerClass, propertyHolder, entityBinder, mappings persistentClass, clazzToProcess, inheritanceStatePerClass, entityBinder, mappings
); );
if ( elements == null ) { if ( elements == null ) {
throw new AnnotationException( "No identifier specified for entity: " + propertyHolder.getEntityName() ); throw new AnnotationException( "No identifier specified for entity: " + propertyHolder.getEntityName() );
@ -650,8 +653,7 @@ else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) )
if ( idClass != null ) { if ( idClass != null ) {
XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() ); XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() );
boolean isComponent = true; boolean isComponent = true;
boolean propertyAnnotated = entityBinder.isPropertyAnnotated( compositeClass ); AccessType propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
String propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
String generatorType = "assigned"; String generatorType = "assigned";
String generator = BinderHelper.ANNOTATION_STRING_DEFAULT; String generator = BinderHelper.ANNOTATION_STRING_DEFAULT;
PropertyData inferredData = new PropertyPreloadedData( PropertyData inferredData = new PropertyPreloadedData(
@ -672,7 +674,6 @@ else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) )
propertyHolder, propertyHolder,
localGenerators, localGenerators,
isComponent, isComponent,
propertyAnnotated,
propertyAccessor, entityBinder, propertyAccessor, entityBinder,
true, true,
false, mappings, inheritanceStatePerClass false, mappings, inheritanceStatePerClass
@ -684,7 +685,6 @@ else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) )
propertyHolder, propertyHolder,
inferredData, inferredData,
baseInferredData, baseInferredData,
propertyAnnotated,
propertyAccessor, false, propertyAccessor, false,
entityBinder, entityBinder,
true, true, true, true,
@ -879,7 +879,7 @@ private static boolean isEntityClassType(XClass clazzToProcess, AnnotatedClassTy
return true; return true;
} }
/** /*
* Get the annotated elements * Get the annotated elements
* Guess the annotated element from @Id or @EmbeddedId presence * Guess the annotated element from @Id or @EmbeddedId presence
* Change EntityBinder by side effect * Change EntityBinder by side effect
@ -887,9 +887,15 @@ private static boolean isEntityClassType(XClass clazzToProcess, AnnotatedClassTy
private static List<PropertyData> getElementsToProcess( private static List<PropertyData> getElementsToProcess(
PersistentClass persistentClass, XClass clazzToProcess, PersistentClass persistentClass, XClass clazzToProcess,
Map<XClass, InheritanceState> inheritanceStatePerClass, Map<XClass, InheritanceState> inheritanceStatePerClass,
PropertyHolder propertyHolder, EntityBinder entityBinder, ExtendedMappings mappings EntityBinder entityBinder, ExtendedMappings mappings
) { ) {
InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess ); InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess );
assert !inheritanceState.isEmbeddableSuperclass();
AccessType accessType = determineExplicitAccessType(
clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState
);
List<XClass> classesToProcess = getMappedSuperclassesTillNextEntityOrdered( List<XClass> classesToProcess = getMappedSuperclassesTillNextEntityOrdered(
persistentClass, clazzToProcess, inheritanceStatePerClass, mappings persistentClass, clazzToProcess, inheritanceStatePerClass, mappings
); );
@ -897,53 +903,14 @@ private static List<PropertyData> getElementsToProcess(
int deep = classesToProcess.size(); int deep = classesToProcess.size();
boolean hasIdentifier = false; boolean hasIdentifier = false;
assert !inheritanceState.isEmbeddableSuperclass();
Boolean isExplicitPropertyAnnotated = null;
String explicitAccessType;
if ( inheritanceState.hasParents() ) {
InheritanceState superEntityState =
InheritanceState.getInheritanceStateOfSuperEntity(
clazzToProcess, inheritanceStatePerClass, mappings.getReflectionManager()
);
isExplicitPropertyAnnotated = superEntityState != null ?
superEntityState.isPropertyAnnotated() :
null;
explicitAccessType = superEntityState != null ?
superEntityState.getAccessType() :
null;
}
else {
//the are the root entity but we might have mapped superclasses that contain the id class
AccessType access = clazzToProcess.getAnnotation( AccessType.class );
explicitAccessType = access != null ?
access.value() :
null;
if ( "property".equals( explicitAccessType ) ) {
isExplicitPropertyAnnotated = Boolean.TRUE;
}
else if ( "field".equals( explicitAccessType ) ) {
isExplicitPropertyAnnotated = Boolean.FALSE;
}
}
Boolean isPropertyAnnotated = isExplicitPropertyAnnotated == null ?
Boolean.TRUE :
//default to property and fallback if needed
isExplicitPropertyAnnotated;
String accessType = explicitAccessType != null ?
explicitAccessType :
"property";
/* /*
* delay the exception in case field access is used * delay the exception in case field access is used
*/ */
AnnotationException exceptionWhileWalkingElements = null; AnnotationException exceptionWhileWalkingElements = null;
try { try {
for (int index = 0; index < deep; index++) { for (int index = 0; index < deep; index++) {
XClass clazz = classesToProcess.get( index ); PropertyContainer properyContainer = new PropertyContainer( classesToProcess.get( index ) );
boolean currentHasIdentifier = addElementsOfClass( elements, accessType , properyContainer, mappings );
boolean currentHasIdentifier = addElementsOfAClass(
elements, propertyHolder, isPropertyAnnotated,
accessType, clazz, mappings
);
hasIdentifier = hasIdentifier || currentHasIdentifier; hasIdentifier = hasIdentifier || currentHasIdentifier;
} }
} }
@ -952,37 +919,79 @@ else if ( "field".equals( explicitAccessType ) ) {
} }
if ( !hasIdentifier && !inheritanceState.hasParents() ) { if ( !hasIdentifier && !inheritanceState.hasParents() ) {
if ( isExplicitPropertyAnnotated != null ) { if ( AccessType.PROPERTY.equals( accessType ) ) {
//the original exception is legitimate //the original exception is legitimate
if ( exceptionWhileWalkingElements != null) throw exceptionWhileWalkingElements; if ( exceptionWhileWalkingElements != null) throw exceptionWhileWalkingElements;
return null; //explicit but no @Id: the upper layer will raise an exception return null; //explicit but no @Id: the upper layer will raise an exception
} }
isPropertyAnnotated = !isPropertyAnnotated; accessType = AccessType.FIELD;
accessType = "field";
elements.clear(); elements.clear();
for (int index = 0; index < deep; index++) { for (int index = 0; index < deep; index++) {
XClass clazz = classesToProcess.get( index ); PropertyContainer properyContainer = new PropertyContainer( classesToProcess.get( index ) );
boolean currentHasIdentifier = addElementsOfAClass( boolean currentHasIdentifier = addElementsOfClass(elements, accessType, properyContainer, mappings );
elements, propertyHolder, isPropertyAnnotated,
accessType, clazz, mappings
);
hasIdentifier = hasIdentifier || currentHasIdentifier; hasIdentifier = hasIdentifier || currentHasIdentifier;
} }
} }
//the field show no id, fallback tot he original exception //the field show no id, fallback to he original exception
if (!hasIdentifier && exceptionWhileWalkingElements != null) throw exceptionWhileWalkingElements; if (!hasIdentifier && exceptionWhileWalkingElements != null) throw exceptionWhileWalkingElements;
//TODO set the access type here?
entityBinder.setPropertyAnnotated( isPropertyAnnotated );
entityBinder.setPropertyAccessor( accessType ); entityBinder.setPropertyAccessor( accessType );
inheritanceState.setPropertyAnnotated( isPropertyAnnotated );
inheritanceState.setAccessType( accessType ); inheritanceState.setAccessType( accessType );
return hasIdentifier || inheritanceState.hasParents() ? return hasIdentifier || inheritanceState.hasParents() ?
elements : elements :
null; null;
} }
/*
* Check whether either the class itself or any of its super classes explicitly defines a value access strategy.
*
* @return {@code AccessType.FIELD} or {@code AccessType.PROPERTY} in case there is an explicit value,
* {@code AccessType.DEFAULT} otherwise.
*/
private static AccessType determineExplicitAccessType(XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass, ExtendedMappings mappings, InheritanceState inheritanceState) {
AccessType explicitAccessType = AccessType.DEFAULT;
// check whether any of the super classes or the class itself
if ( inheritanceState.hasParents() ) {
InheritanceState superEntityState =
InheritanceState.getInheritanceStateOfSuperEntity(
clazzToProcess, inheritanceStatePerClass, mappings.getReflectionManager()
);
if ( superEntityState != null ) {
explicitAccessType = superEntityState.getAccessType();
}
}
else {
AccessType hibernateExplicitAccessType = AccessType.DEFAULT;
AccessType jpaExplicitAccessType = AccessType.DEFAULT;
//the are the root entity but we might have mapped superclasses that contain the id class
org.hibernate.annotations.AccessType accessType = clazzToProcess.getAnnotation( org.hibernate.annotations.AccessType.class );
if ( accessType != null ) {
hibernateExplicitAccessType = AccessType.getAccessStrategy( accessType.value() );
}
Access access = clazzToProcess.getAnnotation( Access.class );
if( access != null ) {
jpaExplicitAccessType = AccessType.getAccessStrategy( access.value() );
}
if ( hibernateExplicitAccessType != AccessType.DEFAULT
&& jpaExplicitAccessType != AccessType.DEFAULT
&& hibernateExplicitAccessType != jpaExplicitAccessType ) {
throw new MappingException( "@AccessType and @Access specified with contradicting values. Use of @Access only is recommended. " );
}
if(hibernateExplicitAccessType != AccessType.DEFAULT) {
explicitAccessType = hibernateExplicitAccessType;
} else {
explicitAccessType = jpaExplicitAccessType;
}
}
return explicitAccessType;
}
private static List<XClass> getMappedSuperclassesTillNextEntityOrdered( private static List<XClass> getMappedSuperclassesTillNextEntityOrdered(
PersistentClass persistentClass, XClass annotatedClass, PersistentClass persistentClass, XClass annotatedClass,
Map<XClass, InheritanceState> inheritanceStatePerClass, Map<XClass, InheritanceState> inheritanceStatePerClass,
@ -1035,7 +1044,7 @@ private static List<XClass> getMappedSuperclassesTillNextEntityOrdered(
return classesToProcess; return classesToProcess;
} }
/** /*
* Process the filters defined on the given class, as well as all filters defined * Process the filters defined on the given class, as well as all filters defined
* on the MappedSuperclass(s) in the inheritance hierarchy * on the MappedSuperclass(s) in the inheritance hierarchy
*/ */
@ -1151,95 +1160,35 @@ private static void bindDiscriminatorToPersistentClass(
} }
/** /**
* Add elements of a class *
* @param elements List of {@code ProperyData} instances
* @param propertyAccessor The default value access strategy which has to be used in case no explicit local access
* strategy is used
* @param propertyContainer Metadata about a class and its properties
* @param mappings Mapping meta data
* @return {@code true} in case an id property was found while iterating the elements of {@code annoatedClass} using
* the determined access strategy, {@code false} otherwise.
*/ */
private static boolean addElementsOfAClass( private static boolean addElementsOfClass(
List<PropertyData> elements, PropertyHolder propertyHolder, boolean isPropertyAnnotated, List<PropertyData> elements, AccessType propertyAccessor, PropertyContainer propertyContainer, ExtendedMappings mappings
String propertyAccessor, final XClass annotatedClass, ExtendedMappings mappings
) { ) {
boolean hasIdentifier = false; boolean hasIdentifier = false;
AccessType access = annotatedClass.getAnnotation( AccessType.class ); AccessType classDefinedAccessType = propertyContainer.getDefaultAccessStrategy();
String localPropertyAccessor = access != null ?
access.value() :
null;
String accessType;
if ( "property".equals( localPropertyAccessor ) || "field".equals( localPropertyAccessor ) ) {
accessType = localPropertyAccessor;
}
else {
if ( localPropertyAccessor == null ) {
localPropertyAccessor = propertyAccessor;
}
if ( isPropertyAnnotated ) { if ( classDefinedAccessType.equals( AccessType.DEFAULT ) ) {
accessType = "property"; classDefinedAccessType = propertyAccessor;
}
else {
accessType = "field";
}
} }
log.debug( "Processing {} {} annotation", propertyHolder.getEntityName(), accessType ); Collection<XProperty> properties = propertyContainer.getProperties( classDefinedAccessType );
List<XProperty> properties = annotatedClass.getDeclaredProperties( accessType ); for ( XProperty p : properties ) {
//order so that property are used in the same order when binding native query final boolean currentHasIdentifier = addProperty(
Collections.sort( properties, new Comparator<XProperty>() { propertyContainer.getXClass(), p, elements, classDefinedAccessType.getType(), mappings
public int compare(XProperty property1, XProperty property2) { );
return property1.getName().compareTo( property2.getName() );
}
} );
for (XProperty p : properties) {
if ( !p.isTypeResolved() && !discoverTypeWithoutReflection( p ) && !mustBeSkipped( p, mappings ) ) {
throw new AnnotationException(
"Property " + StringHelper.qualify( propertyHolder.getEntityName(), p.getName() ) +
" has an unbound type and no explicit target entity. Resolve this Generic usage issue" +
" or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type"
);
}
final boolean currentHasIdentifier = addProperty( annotatedClass, p, elements, localPropertyAccessor, mappings );
hasIdentifier = hasIdentifier || currentHasIdentifier; hasIdentifier = hasIdentifier || currentHasIdentifier;
} }
return hasIdentifier; return hasIdentifier;
} }
private static boolean discoverTypeWithoutReflection(XProperty p) {
if ( p.isAnnotationPresent( OneToOne.class ) && !p.getAnnotation( OneToOne.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( OneToMany.class ) && !p.getAnnotation( OneToMany.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( ManyToOne.class ) && !p.getAnnotation( ManyToOne.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( ManyToMany.class ) && !p.getAnnotation( ManyToMany.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( ManyToAny.class ) ) {
if ( !p.isCollection() && !p.isArray() ) {
throw new AnnotationException( "@ManyToAny used on a non collection non array property: " + p.getName() );
}
return true;
}
else if ( p.isAnnotationPresent( Type.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( Target.class ) ) {
return true;
}
return false;
}
private static boolean addProperty( private static boolean addProperty(
XClass declaringClass, XProperty property, List<PropertyData> annElts, XClass declaringClass, XProperty property, List<PropertyData> annElts,
String propertyAccessor, ExtendedMappings mappings String propertyAccessor, ExtendedMappings mappings
@ -1248,32 +1197,25 @@ private static boolean addProperty(
PropertyData propertyAnnotatedElement = new PropertyInferredData( PropertyData propertyAnnotatedElement = new PropertyInferredData(
declaringClass, property, propertyAccessor, declaringClass, property, propertyAccessor,
mappings.getReflectionManager() ); mappings.getReflectionManager() );
if ( !mustBeSkipped( propertyAnnotatedElement.getProperty(), mappings ) ) {
/* /*
* put element annotated by @Id in front * put element annotated by @Id in front
* since it has to be parsed before any association by Hibernate * since it has to be parsed before any association by Hibernate
*/ */
final XAnnotatedElement element = propertyAnnotatedElement.getProperty(); final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) { if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) {
annElts.add( 0, propertyAnnotatedElement ); annElts.add( 0, propertyAnnotatedElement );
hasIdentifier = true; hasIdentifier = true;
}
else {
annElts.add( propertyAnnotatedElement );
hasIdentifier = false;
}
} }
else {
annElts.add( propertyAnnotatedElement );
hasIdentifier = false;
}
return hasIdentifier; return hasIdentifier;
} }
private static boolean mustBeSkipped(XProperty property, ExtendedMappings mappings) { /*
//TODO make those hardcoded tests more portable (through the bytecode provider?)
return property.isAnnotationPresent( Transient.class )
|| "net.sf.cglib.transform.impl.InterceptFieldCallback".equals( property.getType().getName() )
|| "org.hibernate.bytecode.javassist.FieldHandler".equals( property.getType().getName() );
}
/**
* Process annotation of a particular property * Process annotation of a particular property
*/ */
private static void processElementAnnotations( private static void processElementAnnotations(
@ -1434,9 +1376,7 @@ else if ( joinColumns == null && property.isAnnotationPresent( org.hibernate.ann
//guess if its a component and find id data access (property, field etc) //guess if its a component and find id data access (property, field etc)
final boolean isComponent = returnedClass.isAnnotationPresent( Embeddable.class ) final boolean isComponent = returnedClass.isAnnotationPresent( Embeddable.class )
|| property.isAnnotationPresent( EmbeddedId.class ); || property.isAnnotationPresent( EmbeddedId.class );
boolean propertyAnnotated = entityBinder.isPropertyAnnotated( returnedClass ); AccessType propertyAccessor = entityBinder.getPropertyAccessor( returnedClass );
String propertyAccessor = entityBinder.getPropertyAccessor( returnedClass );
//if ( isComponent && embeddableAnn != null && embeddableAnn.access() == AccessType.FIELD ) propertyAccess = false;
GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class ); GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
String generatorType = generatedValue != null ? String generatorType = generatedValue != null ?
@ -1455,7 +1395,6 @@ else if ( joinColumns == null && property.isAnnotationPresent( org.hibernate.ann
propertyHolder, propertyHolder,
localGenerators, localGenerators,
isComponent, isComponent,
propertyAnnotated,
propertyAccessor, entityBinder, propertyAccessor, entityBinder,
false, false,
isIdentifierMapper, isIdentifierMapper,
@ -1491,7 +1430,7 @@ else if ( property.isAnnotationPresent( Version.class ) ) {
propBinder.setName( inferredData.getPropertyName() ); propBinder.setName( inferredData.getPropertyName() );
propBinder.setReturnedClassName( inferredData.getTypeName() ); propBinder.setReturnedClassName( inferredData.getTypeName() );
propBinder.setLazy( false ); propBinder.setLazy( false );
propBinder.setPropertyAccessorName( inferredData.getDefaultAccess() ); propBinder.setAccessType( inferredData.getDefaultAccess() );
propBinder.setColumns( columns ); propBinder.setColumns( columns );
propBinder.setHolder( propertyHolder ); //PropertyHolderBuilder.buildPropertyHolder(rootClass) propBinder.setHolder( propertyHolder ); //PropertyHolderBuilder.buildPropertyHolder(rootClass)
propBinder.setProperty( property ); propBinder.setProperty( property );
@ -1673,7 +1612,7 @@ else if ( property.isAnnotationPresent( OneToMany.class )
collectionBinder.setIgnoreNotFound( ignoreNotFound ); collectionBinder.setIgnoreNotFound( ignoreNotFound );
collectionBinder.setCollectionType( inferredData.getProperty().getElementClass() ); collectionBinder.setCollectionType( inferredData.getProperty().getElementClass() );
collectionBinder.setMappings( mappings ); collectionBinder.setMappings( mappings );
collectionBinder.setPropertyAccessorName( inferredData.getDefaultAccess() ); collectionBinder.setAccessType( inferredData.getDefaultAccess() );
Ejb3Column[] elementColumns; Ejb3Column[] elementColumns;
PropertyData virtualProperty = new WrappedInferredData( inferredData, "element" ); PropertyData virtualProperty = new WrappedInferredData( inferredData, "element" );
@ -1887,13 +1826,9 @@ else if ( property.isAnnotationPresent( ManyToAny.class ) ) {
isComponent = embeddedAnn != null || embeddableAnn != null; isComponent = embeddedAnn != null || embeddableAnn != null;
if ( isComponent ) { if ( isComponent ) {
//process component object AccessType propertyAccessor = entityBinder.getPropertyAccessor( property );
//boolean propertyAccess = true;
//if ( embeddableAnn != null && embeddableAnn.access() == AccessType.FIELD ) propertyAccess = false;
boolean propertyAnnotated = entityBinder.isPropertyAnnotated( property );
String propertyAccessor = entityBinder.getPropertyAccessor( property );
bindComponent( bindComponent(
inferredData, propertyHolder, propertyAnnotated, propertyAccessor, entityBinder, inferredData, propertyHolder, propertyAccessor, entityBinder,
isIdentifierMapper, isIdentifierMapper,
mappings, isComponentEmbedded, inheritanceStatePerClass mappings, isComponentEmbedded, inheritanceStatePerClass
); );
@ -1919,7 +1854,7 @@ else if ( property.isAnnotationPresent( ManyToAny.class ) ) {
propBinder.setName( inferredData.getPropertyName() ); propBinder.setName( inferredData.getPropertyName() );
propBinder.setReturnedClassName( inferredData.getTypeName() ); propBinder.setReturnedClassName( inferredData.getTypeName() );
propBinder.setLazy( lazy ); propBinder.setLazy( lazy );
propBinder.setPropertyAccessorName( inferredData.getDefaultAccess() ); propBinder.setAccessType( inferredData.getDefaultAccess() );
propBinder.setColumns( columns ); propBinder.setColumns( columns );
propBinder.setHolder( propertyHolder ); propBinder.setHolder( propertyHolder );
propBinder.setProperty( property ); propBinder.setProperty( property );
@ -2038,14 +1973,13 @@ private static void bindJoinedTableAssociation(
private static void bindComponent( private static void bindComponent(
PropertyData inferredData, PropertyData inferredData,
PropertyHolder propertyHolder, PropertyHolder propertyHolder,
boolean propertyAnnotated, AccessType propertyAccessor, EntityBinder entityBinder,
String propertyAccessor, EntityBinder entityBinder,
boolean isIdentifierMapper, boolean isIdentifierMapper,
ExtendedMappings mappings, boolean isComponentEmbedded, ExtendedMappings mappings, boolean isComponentEmbedded,
Map<XClass, InheritanceState> inheritanceStatePerClass Map<XClass, InheritanceState> inheritanceStatePerClass
) { ) {
Component comp = fillComponent( Component comp = fillComponent(
propertyHolder, inferredData, propertyAnnotated, propertyAccessor, true, entityBinder, propertyHolder, inferredData, propertyAccessor, true, entityBinder,
isComponentEmbedded, isIdentifierMapper, isComponentEmbedded, isIdentifierMapper,
false, mappings, inheritanceStatePerClass false, mappings, inheritanceStatePerClass
); );
@ -2056,28 +1990,27 @@ private static void bindComponent(
binder.setName( inferredData.getPropertyName() ); binder.setName( inferredData.getPropertyName() );
binder.setValue( comp ); binder.setValue( comp );
binder.setProperty( inferredData.getProperty() ); binder.setProperty( inferredData.getProperty() );
binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); binder.setAccessType( inferredData.getDefaultAccess() );
Property prop = binder.make(); Property prop = binder.make();
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() ); propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
} }
public static Component fillComponent( public static Component fillComponent(
PropertyHolder propertyHolder, PropertyData inferredData, PropertyHolder propertyHolder, PropertyData inferredData,
boolean propertyAnnotated, String propertyAccessor, boolean isNullable, AccessType propertyAccessor, boolean isNullable,
EntityBinder entityBinder, EntityBinder entityBinder,
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass,
ExtendedMappings mappings, Map<XClass, InheritanceState> inheritanceStatePerClass ExtendedMappings mappings, Map<XClass, InheritanceState> inheritanceStatePerClass
) { ) {
return fillComponent(propertyHolder, inferredData, null, propertyAnnotated, propertyAccessor, return fillComponent(propertyHolder, inferredData, null, propertyAccessor,
isNullable, entityBinder, isComponentEmbedded, isIdentifierMapper, inSecondPass, mappings, isNullable, entityBinder, isComponentEmbedded, isIdentifierMapper, inSecondPass, mappings,
inheritanceStatePerClass); inheritanceStatePerClass);
} }
public static Component fillComponent( public static Component fillComponent(
PropertyHolder propertyHolder, PropertyData inferredData, PropertyData baseInferredData, PropertyHolder propertyHolder, PropertyData inferredData, PropertyData baseInferredData,
boolean propertyAnnotated, String propertyAccessor, boolean isNullable, AccessType propertyAccessor, boolean isNullable, EntityBinder entityBinder,
EntityBinder entityBinder,
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings, boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass Map<XClass, InheritanceState> inheritanceStatePerClass
) { ) {
@ -2113,39 +2046,24 @@ public static Component fillComponent(
PropertyHolder baseSubHolder; PropertyHolder baseSubHolder;
if(baseInferredData != null) if(baseInferredData != null)
{ {
baseSubHolder = PropertyHolderBuilder.buildPropertyHolder(
comp, subpath,
inferredData, propertyHolder, mappings
);
baseClassElements = new ArrayList<PropertyData>(); baseClassElements = new ArrayList<PropertyData>();
baseReturnedClassOrElement = baseInferredData.getClassOrElement(); baseReturnedClassOrElement = baseInferredData.getClassOrElement();
bindTypeDefs(baseReturnedClassOrElement, mappings); bindTypeDefs(baseReturnedClassOrElement, mappings);
addElementsOfAClass( PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement );
baseClassElements, addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
baseSubHolder,
propertyAnnotated,
propertyAccessor, baseReturnedClassOrElement, mappings
);
} }
//embeddable elements can have type defs //embeddable elements can have type defs
bindTypeDefs(returnedClassOrElement, mappings); bindTypeDefs(returnedClassOrElement, mappings);
addElementsOfAClass( PropertyContainer propContainer = new PropertyContainer( returnedClassOrElement );
classElements, addElementsOfClass( classElements, propertyAccessor, propContainer, mappings);
subHolder,
propertyAnnotated,
propertyAccessor, returnedClassOrElement, mappings
);
//add elements of the embeddable superclass //add elements of the embeddable superclass
XClass superClass = inferredData.getPropertyClass().getSuperclass(); XClass superClass = inferredData.getPropertyClass().getSuperclass();
while ( superClass != null && superClass.isAnnotationPresent( MappedSuperclass.class ) ) { while ( superClass != null && superClass.isAnnotationPresent( MappedSuperclass.class ) ) {
//FIXME: proper support of typevariables incl var resolved at upper levels //FIXME: proper support of typevariables incl var resolved at upper levels
addElementsOfAClass( propContainer = new PropertyContainer( superClass );
classElements, addElementsOfClass( classElements, propertyAccessor, propContainer, mappings );
subHolder,
entityBinder.isPropertyAnnotated( superClass ),
propertyAccessor, superClass, mappings
);
superClass = superClass.getSuperclass(); superClass = superClass.getSuperclass();
} }
if ( baseClassElements != null ) { if ( baseClassElements != null ) {
@ -2173,14 +2091,13 @@ private static void bindId(
PropertyData inferredData, Ejb3Column[] columns, PropertyHolder propertyHolder, PropertyData inferredData, Ejb3Column[] columns, PropertyHolder propertyHolder,
Map<String, IdGenerator> localGenerators, Map<String, IdGenerator> localGenerators,
boolean isComposite, boolean isComposite,
boolean isPropertyAnnotated, AccessType propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
boolean isIdentifierMapper, ExtendedMappings mappings, boolean isIdentifierMapper, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass Map<XClass, InheritanceState> inheritanceStatePerClass
) { ) {
bindId(generatorType, generatorName, inferredData, null, columns, propertyHolder, bindId(generatorType, generatorName, inferredData, null, columns, propertyHolder,
localGenerators, isComposite, isPropertyAnnotated, propertyAccessor, entityBinder, localGenerators, isComposite, propertyAccessor, entityBinder,
isEmbedded, isIdentifierMapper, mappings, inheritanceStatePerClass); isEmbedded, isIdentifierMapper, mappings, inheritanceStatePerClass);
} }
@ -2189,8 +2106,7 @@ private static void bindId(
PropertyData baseInferredData, Ejb3Column[] columns, PropertyHolder propertyHolder, PropertyData baseInferredData, Ejb3Column[] columns, PropertyHolder propertyHolder,
Map<String, IdGenerator> localGenerators, Map<String, IdGenerator> localGenerators,
boolean isComposite, boolean isComposite,
boolean isPropertyAnnotated, AccessType propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
boolean isIdentifierMapper, ExtendedMappings mappings, boolean isIdentifierMapper, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass Map<XClass, InheritanceState> inheritanceStatePerClass
) { ) {
@ -2210,7 +2126,7 @@ private static void bindId(
SimpleValue id; SimpleValue id;
if ( isComposite ) { if ( isComposite ) {
id = fillComponent( id = fillComponent(
propertyHolder, inferredData, baseInferredData, isPropertyAnnotated, propertyAccessor, propertyHolder, inferredData, baseInferredData, propertyAccessor,
false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings, inheritanceStatePerClass false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings, inheritanceStatePerClass
); );
Component componentId = (Component) id; Component componentId = (Component) id;
@ -2247,7 +2163,7 @@ private static void bindId(
PropertyBinder binder = new PropertyBinder(); PropertyBinder binder = new PropertyBinder();
binder.setName( inferredData.getPropertyName() ); binder.setName( inferredData.getPropertyName() );
binder.setValue( id ); binder.setValue( id );
binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); binder.setAccessType( inferredData.getDefaultAccess() );
binder.setProperty( inferredData.getProperty() ); binder.setProperty( inferredData.getProperty() );
Property prop = binder.make(); Property prop = binder.make();
rootClass.setIdentifierProperty( prop ); rootClass.setIdentifierProperty( prop );
@ -2345,7 +2261,7 @@ private static void bindManyToOne(
binder.setInsertable( columns[0].isInsertable() ); binder.setInsertable( columns[0].isInsertable() );
binder.setUpdatable( columns[0].isUpdatable() ); binder.setUpdatable( columns[0].isUpdatable() );
} }
binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); binder.setAccessType( inferredData.getDefaultAccess() );
binder.setCascade( cascadeStrategy ); binder.setCascade( cascadeStrategy );
binder.setProperty(inferredData.getProperty()); binder.setProperty(inferredData.getProperty());
Property prop = binder.make(); Property prop = binder.make();
@ -2496,7 +2412,7 @@ private static void bindAny(
binder.setInsertable( columns[0].isInsertable() ); binder.setInsertable( columns[0].isInsertable() );
binder.setUpdatable( columns[0].isUpdatable() ); binder.setUpdatable( columns[0].isUpdatable() );
} }
binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); binder.setAccessType( inferredData.getDefaultAccess() );
binder.setCascade( cascadeStrategy ); binder.setCascade( cascadeStrategy );
Property prop = binder.make(); Property prop = binder.make();
//composite FK columns are in the same table so its OK //composite FK columns are in the same table so its OK
@ -2556,15 +2472,12 @@ private static String getCascadeStrategy(
hibernateCascadeAnnotation.value(); hibernateCascadeAnnotation.value();
if ( hibernateCascades != null && hibernateCascades.length > 0 ) { if ( hibernateCascades != null && hibernateCascades.length > 0 ) {
for (CascadeType cascadeType : hibernateCascades) { hibernateCascadeSet.addAll( Arrays.asList( hibernateCascades ) );
hibernateCascadeSet.add( cascadeType );
}
} }
StringBuilder cascade = new StringBuilder(); StringBuilder cascade = new StringBuilder();
Iterator<CascadeType> cascadeType = hibernateCascadeSet.iterator(); for ( CascadeType aHibernateCascadeSet : hibernateCascadeSet ) {
while ( cascadeType.hasNext() ) { switch ( aHibernateCascadeSet ) {
switch ( cascadeType.next() ) {
case ALL: case ALL:
cascade.append( "," ).append( "all" ); cascade.append( "," ).append( "all" );
break; break;

View File

@ -60,8 +60,7 @@ public InheritanceState(XClass clazz) {
/** /**
* only defined on embedded superclasses * only defined on embedded superclasses
*/ */
private String accessType = null; private AccessType accessType = AccessType.DEFAULT;
private Boolean isPropertyAnnotated;
private void extractInheritanceType() { private void extractInheritanceType() {
XAnnotatedElement element = getClazz(); XAnnotatedElement element = getClazz();
@ -108,7 +107,9 @@ public static InheritanceState getSuperclassInheritanceState(
do { do {
superclass = superclass.getSuperclass(); superclass = superclass.getSuperclass();
InheritanceState currentState = states.get( superclass ); InheritanceState currentState = states.get( superclass );
if ( currentState != null ) return currentState; if ( currentState != null ) {
return currentState;
}
} }
while ( superclass != null && !reflectionManager.equals( superclass, Object.class ) ); while ( superclass != null && !reflectionManager.equals( superclass, Object.class ) );
return null; return null;
@ -154,19 +155,11 @@ public void setEmbeddableSuperclass(boolean embeddableSuperclass) {
isEmbeddableSuperclass = embeddableSuperclass; isEmbeddableSuperclass = embeddableSuperclass;
} }
public String getAccessType() { public AccessType getAccessType() {
return accessType; return accessType;
} }
public void setAccessType(String accessType) { public void setAccessType(AccessType type) {
this.accessType = accessType; this.accessType = type;
}
public Boolean isPropertyAnnotated() {
return isPropertyAnnotated;
}
public void setPropertyAnnotated(Boolean propertyAnnotated) {
isPropertyAnnotated = propertyAnnotated;
} }
} }

View File

@ -111,7 +111,7 @@ public void doSecondPass(Map persistentClasses) throws MappingException {
binder.setName( propertyName ); binder.setName( propertyName );
binder.setValue( value ); binder.setValue( value );
binder.setCascade( cascadeStrategy ); binder.setCascade( cascadeStrategy );
binder.setPropertyAccessorName( inferredData.getDefaultAccess() ); binder.setAccessType( inferredData.getDefaultAccess() );
Property prop = binder.make(); Property prop = binder.make();
if ( BinderHelper.isDefault( mappedBy ) ) { if ( BinderHelper.isDefault( mappedBy ) ) {
/* /*

View File

@ -0,0 +1,233 @@
// $Id:$
/*
* 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.cfg;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.TreeMap;
import javax.persistence.Access;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.AnnotationException;
import org.hibernate.MappingException;
import org.hibernate.annotations.ManyToAny;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
/**
* @author Hardy Ferentschik
*/
/**
* A temporary class where we keep the {@code XProperty}s of a class ordered by access type.
*/
class PropertyContainer {
private static final Logger log = LoggerFactory.getLogger( AnnotationBinder.class );
private final TreeMap<String, XProperty> fieldAccessMap;
private final TreeMap<String, XProperty> propertyAccessMap;
private final XClass xClass;
private final AccessType defaultAccessType;
PropertyContainer(XClass clazz) {
this.xClass = clazz;
fieldAccessMap = initProperties( AccessType.FIELD );
propertyAccessMap = initProperties( AccessType.PROPERTY );
defaultAccessType = determineClassDefinedAccessStrategy();
checkForJpaAccess();
}
public XClass getXClass() {
return xClass;
}
public AccessType getDefaultAccessStrategy() {
return defaultAccessType;
}
public Collection<XProperty> getProperties(AccessType accessType) {
if ( AccessType.DEFAULT == accessType || AccessType.PROPERTY == accessType ) {
return propertyAccessMap.values();
}
else {
return fieldAccessMap.values();
}
}
private void checkForJpaAccess() {
List<XProperty> tmpList = new ArrayList<XProperty>();
for ( XProperty property : fieldAccessMap.values() ) {
Access access = property.getAnnotation( Access.class );
if ( access == null ) {
continue;
}
AccessType accessType = AccessType.getAccessStrategy( access.value() );
if ( accessType == AccessType.PROPERTY ) {
log.warn( "Placing @Access(AccessType.PROPERTY) on a field does not have any effect." );
continue;
}
tmpList.add( property );
}
for ( XProperty property : tmpList ) {
fieldAccessMap.remove( property.getName() );
propertyAccessMap.put( property.getName(), property );
}
tmpList.clear();
for ( XProperty property : propertyAccessMap.values() ) {
Access access = property.getAnnotation( Access.class );
if ( access == null ) {
continue;
}
AccessType accessType = AccessType.getAccessStrategy( access.value() );
if ( accessType == AccessType.FIELD ) {
log.warn( "Placing @Access(AccessType.FIELD) on a field does not have any effect." );
continue;
}
tmpList.add( property );
}
for ( XProperty property : tmpList ) {
propertyAccessMap.remove( property.getName() );
fieldAccessMap.put( property.getName(), property );
}
}
private TreeMap<String, XProperty> initProperties(AccessType access) {
//order so that property are used in the same order when binding native query
TreeMap<String, XProperty> propertiesMap = new TreeMap<String, XProperty>();
List<XProperty> properties = xClass.getDeclaredProperties( access.getType() );
for ( XProperty property : properties ) {
// if ( !property.isTypeResolved() && !discoverTypeWithoutReflection( property )
// && !mustBeSkipped( property ) ) {
// String msg = "Property " + StringHelper.qualify( xClass.getName(), property.getName() ) +
// " has an unbound type and no explicit target entity. Resolve this Generic usage issue" +
// " or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type";
// throw new AnnotationException( msg );
// }
if ( !mustBeSkipped( property ) ) {
propertiesMap.put( property.getName(), property );
}
}
return propertiesMap;
}
private AccessType determineClassDefinedAccessStrategy() {
AccessType classDefinedAccessType;
AccessType hibernateDefinedAccessType = AccessType.DEFAULT;
AccessType jpaDefinedAccessType = AccessType.DEFAULT;
org.hibernate.annotations.AccessType accessType = xClass.getAnnotation( org.hibernate.annotations.AccessType.class );
if ( accessType != null ) {
hibernateDefinedAccessType = AccessType.getAccessStrategy( accessType.value() );
}
Access access = xClass.getAnnotation( Access.class );
if ( access != null ) {
jpaDefinedAccessType = AccessType.getAccessStrategy( access.value() );
}
if ( hibernateDefinedAccessType != AccessType.DEFAULT
&& jpaDefinedAccessType != AccessType.DEFAULT
&& hibernateDefinedAccessType != jpaDefinedAccessType ) {
throw new MappingException(
"@AccessType and @Access specified with contradicting values. Use of @Access only is recommended. "
);
}
if ( hibernateDefinedAccessType != AccessType.DEFAULT ) {
classDefinedAccessType = hibernateDefinedAccessType;
}
else {
classDefinedAccessType = jpaDefinedAccessType;
}
return classDefinedAccessType;
}
private static boolean discoverTypeWithoutReflection(XProperty p) {
if ( p.isAnnotationPresent( OneToOne.class ) && !p.getAnnotation( OneToOne.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( OneToMany.class ) && !p.getAnnotation( OneToMany.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( ManyToOne.class ) && !p.getAnnotation( ManyToOne.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( ManyToMany.class ) && !p.getAnnotation( ManyToMany.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( ManyToAny.class ) ) {
if ( !p.isCollection() && !p.isArray() ) {
throw new AnnotationException( "@ManyToAny used on a non collection non array property: " + p.getName() );
}
return true;
}
else if ( p.isAnnotationPresent( Type.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( Target.class ) ) {
return true;
}
return false;
}
private static boolean mustBeSkipped(XProperty property) {
//TODO make those hardcoded tests more portable (through the bytecode provider?)
return property.isAnnotationPresent( Transient.class )
|| "net.sf.cglib.transform.impl.InterceptFieldCallback".equals( property.getType().getName() )
|| "org.hibernate.bytecode.javassist.FieldHandler".equals( property.getType().getName() );
}
}

View File

@ -33,7 +33,7 @@ public interface PropertyData {
* @return default member access (whether field or property) * @return default member access (whether field or property)
* @throws MappingException No getter or field found or wrong JavaBean spec usage * @throws MappingException No getter or field found or wrong JavaBean spec usage
*/ */
String getDefaultAccess(); AccessType getDefaultAccess();
/** /**
* @return property name * @return property name

View File

@ -23,8 +23,9 @@
*/ */
package org.hibernate.cfg; package org.hibernate.cfg;
import javax.persistence.Access;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.Target; import org.hibernate.annotations.Target;
import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
@ -37,7 +38,7 @@
* @author Paolo Perrotta * @author Paolo Perrotta
*/ */
public class PropertyInferredData implements PropertyData { public class PropertyInferredData implements PropertyData {
private final String defaultAccess; private final AccessType defaultAccess;
private final XProperty property; private final XProperty property;
private final ReflectionManager reflectionManager; private final ReflectionManager reflectionManager;
@ -50,15 +51,45 @@ public class PropertyInferredData implements PropertyData {
public PropertyInferredData(XClass declaringClass, XProperty property, String propertyAccessor, ReflectionManager reflectionManager) { public PropertyInferredData(XClass declaringClass, XProperty property, String propertyAccessor, ReflectionManager reflectionManager) {
this.declaringClass = declaringClass; this.declaringClass = declaringClass;
this.property = property; this.property = property;
this.defaultAccess = propertyAccessor; this.defaultAccess = AccessType.getAccessStrategy( propertyAccessor );
this.reflectionManager = reflectionManager; this.reflectionManager = reflectionManager;
} }
public String getDefaultAccess() throws MappingException { public AccessType getDefaultAccess() throws MappingException {
// if(skip()) AccessType accessType = defaultAccess;
// return defaultAccess;
AccessType access = property.getAnnotation( AccessType.class ); AccessType hibernateAccessType = AccessType.DEFAULT;
return access != null ? access.value() : defaultAccess; AccessType jpaAccessType = AccessType.DEFAULT;
org.hibernate.annotations.AccessType accessTypeAnnotation = property.getAnnotation( org.hibernate.annotations.AccessType.class );
if ( accessTypeAnnotation != null ) {
hibernateAccessType = AccessType.getAccessStrategy( accessTypeAnnotation.value() );
}
Access access = property.getAnnotation( Access.class );
if ( access != null ) {
jpaAccessType = AccessType.getAccessStrategy( access.value() );
}
if ( hibernateAccessType != AccessType.DEFAULT
&& jpaAccessType != AccessType.DEFAULT
&& hibernateAccessType != jpaAccessType ) {
StringBuilder builder = new StringBuilder();
builder.append( property.toString() );
builder.append(
" defines @AccessType and @Access with contradicting values. Use of @Access only is recommended."
);
throw new MappingException( builder.toString() );
}
if ( hibernateAccessType != AccessType.DEFAULT ) {
accessType = hibernateAccessType;
}
else if ( jpaAccessType != AccessType.DEFAULT ) {
accessType = jpaAccessType;
}
return accessType;
} }
public String getPropertyName() throws MappingException { public String getPropertyName() throws MappingException {

View File

@ -28,19 +28,19 @@
import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.annotations.common.reflection.XProperty;
public class PropertyPreloadedData implements PropertyData { public class PropertyPreloadedData implements PropertyData {
private final String defaultAccess; private final AccessType defaultAccess;
private final String propertyName; private final String propertyName;
private final XClass returnedClass; private final XClass returnedClass;
public PropertyPreloadedData(String defaultAccess, String propertyName, XClass returnedClass) { public PropertyPreloadedData(AccessType defaultAccess, String propertyName, XClass returnedClass) {
this.defaultAccess = defaultAccess; this.defaultAccess = defaultAccess;
this.propertyName = propertyName; this.propertyName = propertyName;
this.returnedClass = returnedClass; this.returnedClass = returnedClass;
} }
public String getDefaultAccess() throws MappingException { public AccessType getDefaultAccess() throws MappingException {
return defaultAccess; return defaultAccess;
} }

View File

@ -43,7 +43,7 @@ public String getClassOrElementName() throws MappingException {
return wrappedInferredData.getClassOrElementName(); return wrappedInferredData.getClassOrElementName();
} }
public String getDefaultAccess() { public AccessType getDefaultAccess() {
return wrappedInferredData.getDefaultAccess(); return wrappedInferredData.getDefaultAccess();
} }

View File

@ -76,6 +76,7 @@
import org.hibernate.annotations.common.AssertionFailure; import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotatedClassType; import org.hibernate.cfg.AnnotatedClassType;
import org.hibernate.cfg.AnnotationBinder; import org.hibernate.cfg.AnnotationBinder;
import org.hibernate.cfg.BinderHelper; import org.hibernate.cfg.BinderHelper;
@ -157,6 +158,7 @@ public abstract class CollectionBinder {
protected Map<XClass, InheritanceState> inheritanceStatePerClass; protected Map<XClass, InheritanceState> inheritanceStatePerClass;
private XClass declaringClass; private XClass declaringClass;
private boolean declaringClassSet; private boolean declaringClassSet;
private AccessType accessType;
public void setUpdatable(boolean updatable) { public void setUpdatable(boolean updatable) {
this.updatable = updatable; this.updatable = updatable;
@ -170,17 +172,14 @@ public void setInsertable(boolean insertable) {
this.insertable = insertable; this.insertable = insertable;
} }
public void setCascadeStrategy(String cascadeStrategy) { public void setCascadeStrategy(String cascadeStrategy) {
this.cascadeStrategy = cascadeStrategy; this.cascadeStrategy = cascadeStrategy;
} }
public void setPropertyAccessorName(String propertyAccessorName) { public void setAccessType(AccessType accessType) {
this.propertyAccessorName = propertyAccessorName; this.accessType = accessType;
} }
private String propertyAccessorName;
public void setInverseJoinColumns(Ejb3JoinColumn[] inverseJoinColumns) { public void setInverseJoinColumns(Ejb3JoinColumn[] inverseJoinColumns) {
this.inverseJoinColumns = inverseJoinColumns; this.inverseJoinColumns = inverseJoinColumns;
} }
@ -491,7 +490,7 @@ public void bind() {
if ( cascadeStrategy != null && cascadeStrategy.indexOf( "delete-orphan" ) >= 0 ) { if ( cascadeStrategy != null && cascadeStrategy.indexOf( "delete-orphan" ) >= 0 ) {
collection.setOrphanDelete( true ); collection.setOrphanDelete( true );
} }
binder.setPropertyAccessorName( propertyAccessorName ); binder.setAccessType( accessType );
binder.setProperty( property ); binder.setProperty( property );
binder.setInsertable( insertable ); binder.setInsertable( insertable );
binder.setUpdatable( updatable ); binder.setUpdatable( updatable );
@ -1296,11 +1295,10 @@ else if ( owner.getIdentifierMapper() != null && owner.getIdentifierMapper().get
throw new AssertionFailure( "Unable to guess collection property accessor name" ); throw new AssertionFailure( "Unable to guess collection property accessor name" );
} }
//boolean propertyAccess = embeddable == null || AccessType.PROPERTY.equals( embeddable.access() ); PropertyData inferredData = new PropertyPreloadedData( AccessType.PROPERTY, "element", elementClass );
PropertyData inferredData = new PropertyPreloadedData( "property", "element", elementClass );
//TODO be smart with isNullable //TODO be smart with isNullable
Component component = AnnotationBinder.fillComponent( Component component = AnnotationBinder.fillComponent(
holder, inferredData, isPropertyAnnotated, isPropertyAnnotated ? "property" : "field", true, holder, inferredData, isPropertyAnnotated ? AccessType.PROPERTY : AccessType.FIELD, true,
entityBinder, false, false, entityBinder, false, false,
true, mappings, inheritanceStatePerClass true, mappings, inheritanceStatePerClass
); );

View File

@ -27,6 +27,7 @@
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.persistence.Access;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.JoinTable; import javax.persistence.JoinTable;
@ -38,7 +39,6 @@
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache; import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.CacheConcurrencyStrategy;
@ -60,6 +60,7 @@
import org.hibernate.annotations.Where; import org.hibernate.annotations.Where;
import org.hibernate.annotations.common.reflection.XAnnotatedElement; import org.hibernate.annotations.common.reflection.XAnnotatedElement;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotationBinder; import org.hibernate.cfg.AnnotationBinder;
import org.hibernate.cfg.BinderHelper; import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.Ejb3JoinColumn; import org.hibernate.cfg.Ejb3JoinColumn;
@ -99,7 +100,6 @@ public class EntityBinder {
private ExtendedMappings mappings; private ExtendedMappings mappings;
private Logger log = LoggerFactory.getLogger( EntityBinder.class ); private Logger log = LoggerFactory.getLogger( EntityBinder.class );
private String discriminatorValue = ""; private String discriminatorValue = "";
private boolean isPropertyAnnotated = false;
private boolean dynamicInsert; private boolean dynamicInsert;
private boolean dynamicUpdate; private boolean dynamicUpdate;
private boolean explicitHibernateEntityAnnotation; private boolean explicitHibernateEntityAnnotation;
@ -118,11 +118,7 @@ public class EntityBinder {
private InheritanceState inheritanceState; private InheritanceState inheritanceState;
private boolean ignoreIdAnnotations; private boolean ignoreIdAnnotations;
private boolean cacheLazyProperty; private boolean cacheLazyProperty;
private String propertyAccessor; private AccessType propertyAccessor = AccessType.DEFAULT;
public boolean isPropertyAnnotated() {
return isPropertyAnnotated;
}
/** /**
* Use as a fake one for Collection of elements * Use as a fake one for Collection of elements
@ -847,36 +843,41 @@ public void processComplementaryTableDefinitions(Tables tables) {
} }
} }
public void setPropertyAnnotated(boolean propertyAnnotated) { public AccessType getPropertyAccessor() {
this.isPropertyAnnotated = propertyAnnotated;
}
public String getPropertyAccessor() {
return propertyAccessor; return propertyAccessor;
} }
public void setPropertyAccessor(String propertyAccessor) { public void setPropertyAccessor(AccessType propertyAccessor) {
this.propertyAccessor = propertyAccessor; this.propertyAccessor = propertyAccessor;
} }
public boolean isPropertyAnnotated(XAnnotatedElement element) { public AccessType getPropertyAccessor(XAnnotatedElement element) {
AccessType access = element.getAnnotation( AccessType.class ); AccessType accessType = propertyAccessor;
if ( access == null ) return isPropertyAnnotated;
String propertyAccessor = access.value();
if ( "property".equals( propertyAccessor ) ) {
return Boolean.TRUE;
}
else if ( "field".equals( propertyAccessor ) ) {
return Boolean.FALSE;
}
else {
return isPropertyAnnotated;
}
}
public String getPropertyAccessor(XAnnotatedElement element) { AccessType hibernateAccessType = null;
AccessType access = element.getAnnotation( AccessType.class ); AccessType jpaAccessType = null;
if ( access == null ) return propertyAccessor;
return access.value(); org.hibernate.annotations.AccessType accessTypeAnnotation = element.getAnnotation( org.hibernate.annotations.AccessType.class );
if ( accessTypeAnnotation != null ) {
hibernateAccessType = AccessType.getAccessStrategy( accessTypeAnnotation.value() );
}
Access access = element.getAnnotation( Access.class );
if ( access != null ) {
jpaAccessType = AccessType.getAccessStrategy( access.value() );
}
if ( hibernateAccessType != null && jpaAccessType != null && hibernateAccessType != jpaAccessType ) {
throw new MappingException( " " );
}
if ( hibernateAccessType != null ) {
accessType = hibernateAccessType;
}
else if ( jpaAccessType != null ) {
accessType = jpaAccessType;
}
return accessType;
} }
} }

View File

@ -39,6 +39,7 @@
import org.hibernate.annotations.MapKeyManyToMany; import org.hibernate.annotations.MapKeyManyToMany;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotatedClassType; import org.hibernate.cfg.AnnotatedClassType;
import org.hibernate.cfg.AnnotationBinder; import org.hibernate.cfg.AnnotationBinder;
import org.hibernate.cfg.BinderHelper; import org.hibernate.cfg.BinderHelper;
@ -227,10 +228,10 @@ else if ( property.isAnnotationPresent( MapKeyManyToMany.class ) ) {
//boolean propertyAccess = embeddable == null || AccessType.PROPERTY.equals( embeddable.access() ); //boolean propertyAccess = embeddable == null || AccessType.PROPERTY.equals( embeddable.access() );
//FIXME "index" is it right? //FIXME "index" is it right?
PropertyData inferredData = new PropertyPreloadedData( "property", "index", elementClass ); PropertyData inferredData = new PropertyPreloadedData( AccessType.PROPERTY, "index", elementClass );
//TODO be smart with isNullable //TODO be smart with isNullable
Component component = AnnotationBinder.fillComponent( Component component = AnnotationBinder.fillComponent(
holder, inferredData, isPropertyAnnotated, isPropertyAnnotated ? "property" : "field", true, holder, inferredData, isPropertyAnnotated ? AccessType.PROPERTY : AccessType.FIELD, true,
entityBinder, false, false, entityBinder, false, false,
true, mappings, inheritanceStatePerClass true, mappings, inheritanceStatePerClass
); );

View File

@ -35,6 +35,7 @@
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.annotations.common.AssertionFailure; import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.Ejb3Column; import org.hibernate.cfg.Ejb3Column;
import org.hibernate.cfg.ExtendedMappings; import org.hibernate.cfg.ExtendedMappings;
import org.hibernate.cfg.PropertyHolder; import org.hibernate.cfg.PropertyHolder;
@ -54,7 +55,7 @@ public class PropertyBinder {
private String name; private String name;
private String returnedClassName; private String returnedClassName;
private boolean lazy; private boolean lazy;
private String propertyAccessorName; private AccessType accessType;
private Ejb3Column[] columns; private Ejb3Column[] columns;
private PropertyHolder holder; private PropertyHolder holder;
private ExtendedMappings mappings; private ExtendedMappings mappings;
@ -94,8 +95,8 @@ public void setLazy(boolean lazy) {
this.lazy = lazy; this.lazy = lazy;
} }
public void setPropertyAccessorName(String propertyAccessorName) { public void setAccessType(AccessType accessType) {
this.propertyAccessorName = propertyAccessorName; this.accessType = accessType;
} }
public void setColumns(Ejb3Column[] columns) { public void setColumns(Ejb3Column[] columns) {
@ -170,7 +171,7 @@ public Property make() {
prop.setValue( value ); prop.setValue( value );
prop.setLazy( lazy ); prop.setLazy( lazy );
prop.setCascade( cascade ); prop.setCascade( cascade );
prop.setPropertyAccessorName( propertyAccessorName ); prop.setPropertyAccessorName( accessType.getType() );
Generated ann = property != null ? Generated ann = property != null ?
property.getAnnotation( Generated.class ) : property.getAnnotation( Generated.class ) :
null; null;

View File

@ -0,0 +1,30 @@
// $Id:$
/*
* JBoss, Home of Professional Open Source
* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.hibernate.test.annotations.access;
import javax.persistence.Embeddable;
/**
* @author Hardy Ferentschik
*/
@Embeddable
public class Closet extends Furniture {
int numberOfDoors;
}

View File

@ -0,0 +1,31 @@
// $Id:$
/*
* JBoss, Home of Professional Open Source
* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.hibernate.test.annotations.access;
import javax.persistence.Entity;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Foobar {
String foo;
}

View File

@ -0,0 +1,154 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
/*
* 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.test.annotations.access.jpa;
import junit.framework.TestCase;
import org.hibernate.EntityMode;
import org.hibernate.MappingException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.property.BasicPropertyAccessor;
import org.hibernate.property.DirectPropertyAccessor;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.PojoEntityTuplizer;
/**
* @author Hardy Ferentschik
*/
public class AccessMappingTest extends TestCase {
public void testInconsistentAnnotationPlacement() throws Exception {
AnnotationConfiguration cfg = new AnnotationConfiguration();
cfg.addAnnotatedClass( Course.class );
cfg.addAnnotatedClass( Student.class );
try {
cfg.buildSessionFactory();
fail( "@Id and @OneToMany are not placed consistently in test entities. SessionFactory creation should fail." );
}
catch ( MappingException e ) {
// success
}
}
public void testFieldAnnotationPlacement() throws Exception {
AnnotationConfiguration cfg = new AnnotationConfiguration();
Class<?> classUnderTest = CourseFieldAccess.class;
cfg.addAnnotatedClass( classUnderTest );
cfg.addAnnotatedClass( Student.class );
SessionFactoryImplementor factory = ( SessionFactoryImplementor ) cfg.buildSessionFactory();
EntityMetamodel metaModel = factory.getEntityPersister( classUnderTest.getName() )
.getEntityMetamodel();
PojoEntityTuplizer tuplizer = ( PojoEntityTuplizer ) metaModel.getTuplizer( EntityMode.POJO );
assertTrue(
"Field access should be used.",
tuplizer.getIdentifierGetter() instanceof DirectPropertyAccessor.DirectGetter
);
}
public void testPropertyAnnotationPlacement() throws Exception {
AnnotationConfiguration cfg = new AnnotationConfiguration();
Class<?> classUnderTest = CoursePropertyAccess.class;
cfg.addAnnotatedClass( classUnderTest );
cfg.addAnnotatedClass( Student.class );
SessionFactoryImplementor factory = ( SessionFactoryImplementor ) cfg.buildSessionFactory();
EntityMetamodel metaModel = factory.getEntityPersister( classUnderTest.getName() )
.getEntityMetamodel();
PojoEntityTuplizer tuplizer = ( PojoEntityTuplizer ) metaModel.getTuplizer( EntityMode.POJO );
assertTrue(
"Property access should be used.",
tuplizer.getIdentifierGetter() instanceof BasicPropertyAccessor.BasicGetter
);
}
public void testExplicitPropertyAccessAnnotationsOnProperty() throws Exception {
AnnotationConfiguration cfg = new AnnotationConfiguration();
Class<?> classUnderTest = CourseExplicitPropertyAccess.class;
cfg.addAnnotatedClass( classUnderTest );
cfg.addAnnotatedClass( Student.class );
SessionFactoryImplementor factory = ( SessionFactoryImplementor ) cfg.buildSessionFactory();
EntityMetamodel metaModel = factory.getEntityPersister( classUnderTest.getName() )
.getEntityMetamodel();
PojoEntityTuplizer tuplizer = ( PojoEntityTuplizer ) metaModel.getTuplizer( EntityMode.POJO );
assertTrue(
"Property access should be used.",
tuplizer.getIdentifierGetter() instanceof BasicPropertyAccessor.BasicGetter
);
}
public void testExplicitPropertyAccessAnnotationsOnField() throws Exception {
AnnotationConfiguration cfg = new AnnotationConfiguration();
cfg.addAnnotatedClass( CourseExplicitPropertyAccess3.class );
cfg.addAnnotatedClass( Student.class );
try {
cfg.buildSessionFactory();
fail( "@Id and @OneToMany are not placed consistently in test entities. SessionFactory creation should fail." );
}
catch ( MappingException e ) {
// success
}
}
public void testExplicitPropertyAccessAnnotationsWithHibernateStyleOverride() throws Exception {
AnnotationConfiguration cfg = new AnnotationConfiguration();
Class<?> classUnderTest = CourseExplicitPropertyAccess2.class;
cfg.addAnnotatedClass( classUnderTest );
cfg.addAnnotatedClass( Student.class );
SessionFactoryImplementor factory = ( SessionFactoryImplementor ) cfg.buildSessionFactory();
EntityMetamodel metaModel = factory.getEntityPersister( classUnderTest.getName() )
.getEntityMetamodel();
PojoEntityTuplizer tuplizer = ( PojoEntityTuplizer ) metaModel.getTuplizer( EntityMode.POJO );
assertTrue(
"Field access should be used.",
tuplizer.getIdentifierGetter() instanceof DirectPropertyAccessor.DirectGetter
);
assertTrue(
"Property access should be used.",
tuplizer.getGetter( 0 ) instanceof BasicPropertyAccessor.BasicGetter
);
}
public void testExplicitPropertyAccessAnnotationsWithJpaStyleOverride() throws Exception {
AnnotationConfiguration cfg = new AnnotationConfiguration();
Class<?> classUnderTest = CourseExplicitPropertyAccess4.class;
cfg.addAnnotatedClass( classUnderTest );
cfg.addAnnotatedClass( Student.class );
SessionFactoryImplementor factory = ( SessionFactoryImplementor ) cfg.buildSessionFactory();
EntityMetamodel metaModel = factory.getEntityPersister( classUnderTest.getName() )
.getEntityMetamodel();
PojoEntityTuplizer tuplizer = ( PojoEntityTuplizer ) metaModel.getTuplizer( EntityMode.POJO );
assertTrue(
"Field access should be used.",
tuplizer.getIdentifierGetter() instanceof DirectPropertyAccessor.DirectGetter
);
assertTrue(
"Property access should be used.",
tuplizer.getGetter( 0 ) instanceof BasicPropertyAccessor.BasicGetter
);
}
}

View File

@ -0,0 +1,184 @@
//$Id$
/*
* 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.test.annotations.access.jpa;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.annotations.TestCase;
import org.hibernate.test.annotations.access.Closet;
/**
* @author Emmanuel Bernard
*/
public class AccessTest extends TestCase {
public void testDefaultConfigurationModeIsInherited() throws Exception {
User john = new User();
john.setFirstname( "John" );
john.setLastname( "Doe" );
List<User> friends = new ArrayList<User>();
User friend = new User();
friend.setFirstname( "Jane" );
friend.setLastname( "Doe" );
friends.add( friend );
john.setFriends( friends );
Session s = openSession();
s.persist( john );
Transaction tx = s.beginTransaction();
tx.commit();
s.clear();
tx = s.beginTransaction();
john = (User) s.get( User.class, john.getId() );
assertEquals("Wrong number of friends", 1, john.getFriends().size() );
assertNull( john.firstname );
s.delete( john );
tx.commit();
s.close();
}
public void testSuperclassOverriding() throws Exception {
Furniture fur = new Furniture();
fur.setColor( "Black" );
fur.setName( "Beech" );
fur.isAlive = true;
Session s = openSession();
s.persist( fur );
Transaction tx = s.beginTransaction();
tx.commit();
s.clear();
tx = s.beginTransaction();
fur = (Furniture) s.get( Furniture.class, fur.getId() );
assertFalse( fur.isAlive );
assertNotNull( fur.getColor() );
s.delete( fur );
tx.commit();
s.close();
}
public void testSuperclassNonOverriding() throws Exception {
Furniture fur = new Furniture();
fur.setGod( "Buddha" );
Session s = openSession();
s.persist( fur );
Transaction tx = s.beginTransaction();
tx.commit();
s.clear();
tx = s.beginTransaction();
fur = (Furniture) s.get( Furniture.class, fur.getId() );
assertNotNull( fur.getGod() );
s.delete( fur );
tx.commit();
s.close();
}
public void testPropertyOverriding() throws Exception {
Furniture fur = new Furniture();
fur.weight = 3;
Session s = openSession();
s.persist( fur );
Transaction tx = s.beginTransaction();
tx.commit();
s.clear();
tx = s.beginTransaction();
fur = (Furniture) s.get( Furniture.class, fur.getId() );
assertEquals( 5, fur.weight );
s.delete( fur );
tx.commit();
s.close();
}
public void testNonOverridenSubclass() throws Exception {
Chair chair = new Chair();
chair.setPillow( "Blue" );
Session s = openSession();
s.persist( chair );
Transaction tx = s.beginTransaction();
tx.commit();
s.clear();
tx = s.beginTransaction();
chair = (Chair) s.get( Chair.class, chair.getId() );
assertNull( chair.getPillow() );
s.delete( chair );
tx.commit();
s.close();
}
public void testOverridenSubclass() throws Exception {
BigBed bed = new BigBed();
bed.size = 5;
bed.setQuality( "good" );
Session s = openSession();
s.persist( bed );
Transaction tx = s.beginTransaction();
tx.commit();
s.clear();
tx = s.beginTransaction();
bed = (BigBed) s.get( BigBed.class, bed.getId() );
assertEquals( 5, bed.size );
assertNull( bed.getQuality() );
s.delete( bed );
tx.commit();
s.close();
}
public void testFieldsOverriding() throws Exception {
Gardenshed gs = new Gardenshed();
gs.floors = 4;
Session s = openSession();
s.persist( gs );
Transaction tx = s.beginTransaction();
tx.commit();
s.clear();
tx = s.beginTransaction();
gs = (Gardenshed) s.get( Gardenshed.class, gs.getId() );
assertEquals( 4, gs.floors );
assertEquals( 6, gs.getFloors() );
s.delete( gs );
tx.commit();
s.close();
}
protected Class[] getMappings() {
return new Class[] {
Bed.class,
Chair.class,
Furniture.class,
BigBed.class,
Gardenshed.class,
Closet.class,
Person.class,
User.class
};
}
}

View File

@ -0,0 +1,49 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.Transient;
/**
* @author Emmanuel Bernard
*/
@Entity
@Access(AccessType.PROPERTY)
public class Bed extends Furniture {
String quality;
@Transient
public String getQuality() {
return quality;
}
public void setQuality(String quality) {
this.quality = quality;
}
}

View File

@ -0,0 +1,49 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Being {
@Id
@GeneratedValue
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}

View File

@ -0,0 +1,37 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import javax.persistence.Column;
import javax.persistence.Entity;
/**
* @author Emmanuel Bernard
*/
@Entity
public class BigBed extends Bed {
@Column(name = "bed_size")
public int size;
}

View File

@ -0,0 +1,46 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import javax.persistence.Entity;
import javax.persistence.Transient;
/**
* @author Emmanuel Bernard
*/
@Entity
public class Chair extends Furniture {
@Transient
private String pillow;
public String getPillow() {
return pillow;
}
public void setPillow(String pillow) {
this.pillow = pillow;
}
}

View File

@ -0,0 +1,74 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
/*
* 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.test.annotations.access.jpa;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Course {
@Id
@GeneratedValue
private long id;
private String title;
private List<Student> students;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@OneToMany(cascade = CascadeType.ALL)
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,75 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
/*
* 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.test.annotations.access.jpa;
import java.util.List;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
/**
* @author Hardy Ferentschik
*/
@Entity
@Access(AccessType.PROPERTY)
public class CourseExplicitPropertyAccess {
private long id;
private String title;
private List<Student> students;
@Id
@GeneratedValue
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@OneToMany(cascade = CascadeType.ALL)
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,77 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
/*
* 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.test.annotations.access.jpa;
import java.util.List;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
/**
* @author Hardy Ferentschik
*/
@Entity
@Access(AccessType.PROPERTY)
public class CourseExplicitPropertyAccess2 {
private long id;
private String title;
private List<Student> students;
@Id
@GeneratedValue
@org.hibernate.annotations.AccessType("field")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@OneToMany(cascade = CascadeType.ALL)
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,75 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
/*
* 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.test.annotations.access.jpa;
import java.util.List;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
/**
* @author Hardy Ferentschik
*/
@Entity
@Access(AccessType.PROPERTY)
public class CourseExplicitPropertyAccess3 {
@Id
@GeneratedValue
private long id;
private String title;
@OneToMany(cascade = CascadeType.ALL)
private List<Student> students;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,77 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
/*
* 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.test.annotations.access.jpa;
import java.util.List;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
/**
* @author Hardy Ferentschik
*/
@Entity
@Access(AccessType.PROPERTY)
public class CourseExplicitPropertyAccess4 {
@Access(AccessType.FIELD)
@Id
@GeneratedValue
private long id;
private String title;
private List<Student> students;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@ManyToMany
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,72 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
/*
* 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.test.annotations.access.jpa;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
/**
* @author Hardy Ferentschik
*/
@Entity
public class CourseFieldAccess {
@Id
@GeneratedValue
private long id;
private String title;
@OneToMany(cascade = CascadeType.ALL)
private List<Student> students;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,72 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
/*
* 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.test.annotations.access.jpa;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
/**
* @author Hardy Ferentschik
*/
@Entity
public class CoursePropertyAccess {
private long id;
private String title;
private List<Student> students;
@Id
@GeneratedValue
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@OneToMany(cascade = CascadeType.ALL)
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,72 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import javax.persistence.Access;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Transient;
/**
* @author Emmanuel Bernard
*/
@Entity
@Access(javax.persistence.AccessType.FIELD)
public class Furniture extends Woody {
@Id
@GeneratedValue
private Integer id;
private String brand;
@Transient
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Access(javax.persistence.AccessType.PROPERTY)
public long weight;
public long getWeight() {
return weight + 1;
}
public void setWeight(long weight) {
this.weight = weight + 1;
}
}

View File

@ -0,0 +1,78 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import javax.persistence.Access;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Transient;
/**
* This is the opposite of the Furniture test, as this tries to override the class AccessType("property") with
* the property AccessType("field").
*
* @author Dennis Fleurbaaij
* @since 2007-05-31
*/
@Entity
@Access(javax.persistence.AccessType.PROPERTY)
public class Gardenshed
extends
Woody {
private Integer id;
private String brand;
public long floors;
@Transient
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
// These 2 functions should not return in Hibernate, but the value should come from the field "floors"
@Access(javax.persistence.AccessType.FIELD)
public long getFloors() {
return this.floors + 2;
}
public void setFloors(long floors) {
this.floors = floors + 2;
}
}

View File

@ -0,0 +1,60 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import javax.persistence.Access;
import javax.persistence.Entity;
/**
* @author Hardy Ferentschik
*/
@Entity
// explicitly override the access type to be property (default is field, see Being)
@Access(javax.persistence.AccessType.PROPERTY)
public class Person extends Being {
String firstname;
private String lastname;
public String getFirstname() {
return null;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
}

View File

@ -0,0 +1,59 @@
//$Id: AccessTest.java 15025 2008-08-11 09:14:39Z hardy.ferentschik $
/*
* 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.test.annotations.access.jpa;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Student {
@Id
@GeneratedValue
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,45 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
/**
* @author Emmanuel Bernard
*/
@MappedSuperclass
public class Thingy {
private String god;
@Transient
public String getGod() {
return god;
}
public void setGod(String god) {
this.god = god;
}
}

View File

@ -0,0 +1,48 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
/**
* @author Hardy Ferentschik
*/
@Entity
public class User extends Person {
@OneToMany(cascade = CascadeType.ALL)
private List<User> friends;
public List<User> getFriends() {
return friends;
}
public void setFriends(List<User> friends) {
this.friends = friends;
}
}

View File

@ -0,0 +1,55 @@
//$Id:$
/*
* 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.test.annotations.access.jpa;
import javax.persistence.Access;
import javax.persistence.MappedSuperclass;
/**
* @author Emmanuel Bernard
*/
@MappedSuperclass
@Access(javax.persistence.AccessType.PROPERTY)
public class Woody extends Thingy {
private String color;
private String name;
public boolean isAlive; //shouldn't be persistent
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}