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
*
@ -24,8 +25,8 @@
package org.hibernate.cfg;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
@ -34,6 +35,7 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.persistence.Access;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.DiscriminatorType;
@ -68,7 +70,6 @@ import javax.persistence.SqlResultSetMapping;
import javax.persistence.SqlResultSetMappings;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.persistence.ElementCollection;
import javax.persistence.CollectionTable;
@ -83,7 +84,6 @@ import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.Cascade;
@ -116,10 +116,8 @@ import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Parent;
import org.hibernate.annotations.Proxy;
import org.hibernate.annotations.Sort;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.Tuplizer;
import org.hibernate.annotations.Tuplizers;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;
import org.hibernate.annotations.Where;
@ -424,6 +422,11 @@ public final class AnnotationBinder {
/**
* Bind a class having JSR175 annotations
* 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(
XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass, ExtendedMappings mappings
@ -621,7 +624,7 @@ public final class AnnotationBinder {
// check properties
List<PropertyData> elements =
getElementsToProcess(
persistentClass, clazzToProcess, inheritanceStatePerClass, propertyHolder, entityBinder, mappings
persistentClass, clazzToProcess, inheritanceStatePerClass, entityBinder, mappings
);
if ( elements == null ) {
throw new AnnotationException( "No identifier specified for entity: " + propertyHolder.getEntityName() );
@ -650,8 +653,7 @@ public final class AnnotationBinder {
if ( idClass != null ) {
XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() );
boolean isComponent = true;
boolean propertyAnnotated = entityBinder.isPropertyAnnotated( compositeClass );
String propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
AccessType propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
String generatorType = "assigned";
String generator = BinderHelper.ANNOTATION_STRING_DEFAULT;
PropertyData inferredData = new PropertyPreloadedData(
@ -672,7 +674,6 @@ public final class AnnotationBinder {
propertyHolder,
localGenerators,
isComponent,
propertyAnnotated,
propertyAccessor, entityBinder,
true,
false, mappings, inheritanceStatePerClass
@ -684,7 +685,6 @@ public final class AnnotationBinder {
propertyHolder,
inferredData,
baseInferredData,
propertyAnnotated,
propertyAccessor, false,
entityBinder,
true, true,
@ -879,7 +879,7 @@ public final class AnnotationBinder {
return true;
}
/**
/*
* Get the annotated elements
* Guess the annotated element from @Id or @EmbeddedId presence
* Change EntityBinder by side effect
@ -887,9 +887,15 @@ public final class AnnotationBinder {
private static List<PropertyData> getElementsToProcess(
PersistentClass persistentClass, XClass clazzToProcess,
Map<XClass, InheritanceState> inheritanceStatePerClass,
PropertyHolder propertyHolder, EntityBinder entityBinder, ExtendedMappings mappings
EntityBinder entityBinder, ExtendedMappings mappings
) {
InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess );
assert !inheritanceState.isEmbeddableSuperclass();
AccessType accessType = determineExplicitAccessType(
clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState
);
List<XClass> classesToProcess = getMappedSuperclassesTillNextEntityOrdered(
persistentClass, clazzToProcess, inheritanceStatePerClass, mappings
);
@ -897,53 +903,14 @@ public final class AnnotationBinder {
int deep = classesToProcess.size();
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
*/
AnnotationException exceptionWhileWalkingElements = null;
try {
for (int index = 0; index < deep; index++) {
XClass clazz = classesToProcess.get( index );
boolean currentHasIdentifier = addElementsOfAClass(
elements, propertyHolder, isPropertyAnnotated,
accessType, clazz, mappings
);
PropertyContainer properyContainer = new PropertyContainer( classesToProcess.get( index ) );
boolean currentHasIdentifier = addElementsOfClass( elements, accessType , properyContainer, mappings );
hasIdentifier = hasIdentifier || currentHasIdentifier;
}
}
@ -952,37 +919,79 @@ public final class AnnotationBinder {
}
if ( !hasIdentifier && !inheritanceState.hasParents() ) {
if ( isExplicitPropertyAnnotated != null ) {
if ( AccessType.PROPERTY.equals( accessType ) ) {
//the original exception is legitimate
if ( exceptionWhileWalkingElements != null) throw exceptionWhileWalkingElements;
return null; //explicit but no @Id: the upper layer will raise an exception
}
isPropertyAnnotated = !isPropertyAnnotated;
accessType = "field";
accessType = AccessType.FIELD;
elements.clear();
for (int index = 0; index < deep; index++) {
XClass clazz = classesToProcess.get( index );
boolean currentHasIdentifier = addElementsOfAClass(
elements, propertyHolder, isPropertyAnnotated,
accessType, clazz, mappings
);
PropertyContainer properyContainer = new PropertyContainer( classesToProcess.get( index ) );
boolean currentHasIdentifier = addElementsOfClass(elements, accessType, properyContainer, mappings );
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;
//TODO set the access type here?
entityBinder.setPropertyAnnotated( isPropertyAnnotated );
entityBinder.setPropertyAccessor( accessType );
inheritanceState.setPropertyAnnotated( isPropertyAnnotated );
inheritanceState.setAccessType( accessType );
return hasIdentifier || inheritanceState.hasParents() ?
elements :
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(
PersistentClass persistentClass, XClass annotatedClass,
Map<XClass, InheritanceState> inheritanceStatePerClass,
@ -1035,7 +1044,7 @@ public final class AnnotationBinder {
return classesToProcess;
}
/**
/*
* Process the filters defined on the given class, as well as all filters defined
* on the MappedSuperclass(s) in the inheritance hierarchy
*/
@ -1151,95 +1160,35 @@ public final class AnnotationBinder {
}
/**
* 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(
List<PropertyData> elements, PropertyHolder propertyHolder, boolean isPropertyAnnotated,
String propertyAccessor, final XClass annotatedClass, ExtendedMappings mappings
private static boolean addElementsOfClass(
List<PropertyData> elements, AccessType propertyAccessor, PropertyContainer propertyContainer, ExtendedMappings mappings
) {
boolean hasIdentifier = false;
AccessType access = annotatedClass.getAnnotation( AccessType.class );
String localPropertyAccessor = access != null ?
access.value() :
null;
String accessType;
if ( "property".equals( localPropertyAccessor ) || "field".equals( localPropertyAccessor ) ) {
accessType = localPropertyAccessor;
}
else {
if ( localPropertyAccessor == null ) {
localPropertyAccessor = propertyAccessor;
}
AccessType classDefinedAccessType = propertyContainer.getDefaultAccessStrategy();
if ( isPropertyAnnotated ) {
accessType = "property";
}
else {
accessType = "field";
}
if ( classDefinedAccessType.equals( AccessType.DEFAULT ) ) {
classDefinedAccessType = propertyAccessor;
}
log.debug( "Processing {} {} annotation", propertyHolder.getEntityName(), accessType );
List<XProperty> properties = annotatedClass.getDeclaredProperties( accessType );
//order so that property are used in the same order when binding native query
Collections.sort( properties, new Comparator<XProperty>() {
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 );
Collection<XProperty> properties = propertyContainer.getProperties( classDefinedAccessType );
for ( XProperty p : properties ) {
final boolean currentHasIdentifier = addProperty(
propertyContainer.getXClass(), p, elements, classDefinedAccessType.getType(), mappings
);
hasIdentifier = hasIdentifier || currentHasIdentifier;
}
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(
XClass declaringClass, XProperty property, List<PropertyData> annElts,
String propertyAccessor, ExtendedMappings mappings
@ -1248,32 +1197,25 @@ public final class AnnotationBinder {
PropertyData propertyAnnotatedElement = new PropertyInferredData(
declaringClass, property, propertyAccessor,
mappings.getReflectionManager() );
if ( !mustBeSkipped( propertyAnnotatedElement.getProperty(), mappings ) ) {
/*
* put element annotated by @Id in front
* since it has to be parsed before any association by Hibernate
*/
final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) {
annElts.add( 0, propertyAnnotatedElement );
hasIdentifier = true;
}
else {
annElts.add( propertyAnnotatedElement );
hasIdentifier = false;
}
/*
* put element annotated by @Id in front
* since it has to be parsed before any association by Hibernate
*/
final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) {
annElts.add( 0, propertyAnnotatedElement );
hasIdentifier = true;
}
else {
annElts.add( propertyAnnotatedElement );
hasIdentifier = false;
}
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
*/
private static void processElementAnnotations(
@ -1434,9 +1376,7 @@ public final class AnnotationBinder {
//guess if its a component and find id data access (property, field etc)
final boolean isComponent = returnedClass.isAnnotationPresent( Embeddable.class )
|| property.isAnnotationPresent( EmbeddedId.class );
boolean propertyAnnotated = entityBinder.isPropertyAnnotated( returnedClass );
String propertyAccessor = entityBinder.getPropertyAccessor( returnedClass );
//if ( isComponent && embeddableAnn != null && embeddableAnn.access() == AccessType.FIELD ) propertyAccess = false;
AccessType propertyAccessor = entityBinder.getPropertyAccessor( returnedClass );
GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
String generatorType = generatedValue != null ?
@ -1455,7 +1395,6 @@ public final class AnnotationBinder {
propertyHolder,
localGenerators,
isComponent,
propertyAnnotated,
propertyAccessor, entityBinder,
false,
isIdentifierMapper,
@ -1491,7 +1430,7 @@ public final class AnnotationBinder {
propBinder.setName( inferredData.getPropertyName() );
propBinder.setReturnedClassName( inferredData.getTypeName() );
propBinder.setLazy( false );
propBinder.setPropertyAccessorName( inferredData.getDefaultAccess() );
propBinder.setAccessType( inferredData.getDefaultAccess() );
propBinder.setColumns( columns );
propBinder.setHolder( propertyHolder ); //PropertyHolderBuilder.buildPropertyHolder(rootClass)
propBinder.setProperty( property );
@ -1673,7 +1612,7 @@ public final class AnnotationBinder {
collectionBinder.setIgnoreNotFound( ignoreNotFound );
collectionBinder.setCollectionType( inferredData.getProperty().getElementClass() );
collectionBinder.setMappings( mappings );
collectionBinder.setPropertyAccessorName( inferredData.getDefaultAccess() );
collectionBinder.setAccessType( inferredData.getDefaultAccess() );
Ejb3Column[] elementColumns;
PropertyData virtualProperty = new WrappedInferredData( inferredData, "element" );
@ -1887,13 +1826,9 @@ public final class AnnotationBinder {
isComponent = embeddedAnn != null || embeddableAnn != null;
if ( isComponent ) {
//process component object
//boolean propertyAccess = true;
//if ( embeddableAnn != null && embeddableAnn.access() == AccessType.FIELD ) propertyAccess = false;
boolean propertyAnnotated = entityBinder.isPropertyAnnotated( property );
String propertyAccessor = entityBinder.getPropertyAccessor( property );
AccessType propertyAccessor = entityBinder.getPropertyAccessor( property );
bindComponent(
inferredData, propertyHolder, propertyAnnotated, propertyAccessor, entityBinder,
inferredData, propertyHolder, propertyAccessor, entityBinder,
isIdentifierMapper,
mappings, isComponentEmbedded, inheritanceStatePerClass
);
@ -1919,7 +1854,7 @@ public final class AnnotationBinder {
propBinder.setName( inferredData.getPropertyName() );
propBinder.setReturnedClassName( inferredData.getTypeName() );
propBinder.setLazy( lazy );
propBinder.setPropertyAccessorName( inferredData.getDefaultAccess() );
propBinder.setAccessType( inferredData.getDefaultAccess() );
propBinder.setColumns( columns );
propBinder.setHolder( propertyHolder );
propBinder.setProperty( property );
@ -2038,14 +1973,13 @@ public final class AnnotationBinder {
private static void bindComponent(
PropertyData inferredData,
PropertyHolder propertyHolder,
boolean propertyAnnotated,
String propertyAccessor, EntityBinder entityBinder,
AccessType propertyAccessor, EntityBinder entityBinder,
boolean isIdentifierMapper,
ExtendedMappings mappings, boolean isComponentEmbedded,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
Component comp = fillComponent(
propertyHolder, inferredData, propertyAnnotated, propertyAccessor, true, entityBinder,
propertyHolder, inferredData, propertyAccessor, true, entityBinder,
isComponentEmbedded, isIdentifierMapper,
false, mappings, inheritanceStatePerClass
);
@ -2056,28 +1990,27 @@ public final class AnnotationBinder {
binder.setName( inferredData.getPropertyName() );
binder.setValue( comp );
binder.setProperty( inferredData.getProperty() );
binder.setPropertyAccessorName( inferredData.getDefaultAccess() );
binder.setAccessType( inferredData.getDefaultAccess() );
Property prop = binder.make();
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
}
public static Component fillComponent(
PropertyHolder propertyHolder, PropertyData inferredData,
boolean propertyAnnotated, String propertyAccessor, boolean isNullable,
AccessType propertyAccessor, boolean isNullable,
EntityBinder entityBinder,
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass,
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,
inheritanceStatePerClass);
}
public static Component fillComponent(
PropertyHolder propertyHolder, PropertyData inferredData, PropertyData baseInferredData,
boolean propertyAnnotated, String propertyAccessor, boolean isNullable,
EntityBinder entityBinder,
AccessType propertyAccessor, boolean isNullable, EntityBinder entityBinder,
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
@ -2113,39 +2046,24 @@ public final class AnnotationBinder {
PropertyHolder baseSubHolder;
if(baseInferredData != null)
{
baseSubHolder = PropertyHolderBuilder.buildPropertyHolder(
comp, subpath,
inferredData, propertyHolder, mappings
);
baseClassElements = new ArrayList<PropertyData>();
baseReturnedClassOrElement = baseInferredData.getClassOrElement();
bindTypeDefs(baseReturnedClassOrElement, mappings);
addElementsOfAClass(
baseClassElements,
baseSubHolder,
propertyAnnotated,
propertyAccessor, baseReturnedClassOrElement, mappings
);
PropertyContainer propContainer = new PropertyContainer( baseReturnedClassOrElement );
addElementsOfClass( baseClassElements, propertyAccessor, propContainer, mappings );
}
//embeddable elements can have type defs
bindTypeDefs(returnedClassOrElement, mappings);
addElementsOfAClass(
classElements,
subHolder,
propertyAnnotated,
propertyAccessor, returnedClassOrElement, mappings
);
PropertyContainer propContainer = new PropertyContainer( returnedClassOrElement );
addElementsOfClass( classElements, propertyAccessor, propContainer, mappings);
//add elements of the embeddable superclass
XClass superClass = inferredData.getPropertyClass().getSuperclass();
while ( superClass != null && superClass.isAnnotationPresent( MappedSuperclass.class ) ) {
//FIXME: proper support of typevariables incl var resolved at upper levels
addElementsOfAClass(
classElements,
subHolder,
entityBinder.isPropertyAnnotated( superClass ),
propertyAccessor, superClass, mappings
);
propContainer = new PropertyContainer( superClass );
addElementsOfClass( classElements, propertyAccessor, propContainer, mappings );
superClass = superClass.getSuperclass();
}
if ( baseClassElements != null ) {
@ -2173,14 +2091,13 @@ public final class AnnotationBinder {
PropertyData inferredData, Ejb3Column[] columns, PropertyHolder propertyHolder,
Map<String, IdGenerator> localGenerators,
boolean isComposite,
boolean isPropertyAnnotated,
String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
AccessType propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
boolean isIdentifierMapper, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
bindId(generatorType, generatorName, inferredData, null, columns, propertyHolder,
localGenerators, isComposite, isPropertyAnnotated, propertyAccessor, entityBinder,
localGenerators, isComposite, propertyAccessor, entityBinder,
isEmbedded, isIdentifierMapper, mappings, inheritanceStatePerClass);
}
@ -2189,8 +2106,7 @@ public final class AnnotationBinder {
PropertyData baseInferredData, Ejb3Column[] columns, PropertyHolder propertyHolder,
Map<String, IdGenerator> localGenerators,
boolean isComposite,
boolean isPropertyAnnotated,
String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
AccessType propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
boolean isIdentifierMapper, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
@ -2210,7 +2126,7 @@ public final class AnnotationBinder {
SimpleValue id;
if ( isComposite ) {
id = fillComponent(
propertyHolder, inferredData, baseInferredData, isPropertyAnnotated, propertyAccessor,
propertyHolder, inferredData, baseInferredData, propertyAccessor,
false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings, inheritanceStatePerClass
);
Component componentId = (Component) id;
@ -2247,7 +2163,7 @@ public final class AnnotationBinder {
PropertyBinder binder = new PropertyBinder();
binder.setName( inferredData.getPropertyName() );
binder.setValue( id );
binder.setPropertyAccessorName( inferredData.getDefaultAccess() );
binder.setAccessType( inferredData.getDefaultAccess() );
binder.setProperty( inferredData.getProperty() );
Property prop = binder.make();
rootClass.setIdentifierProperty( prop );
@ -2345,7 +2261,7 @@ public final class AnnotationBinder {
binder.setInsertable( columns[0].isInsertable() );
binder.setUpdatable( columns[0].isUpdatable() );
}
binder.setPropertyAccessorName( inferredData.getDefaultAccess() );
binder.setAccessType( inferredData.getDefaultAccess() );
binder.setCascade( cascadeStrategy );
binder.setProperty(inferredData.getProperty());
Property prop = binder.make();
@ -2496,7 +2412,7 @@ public final class AnnotationBinder {
binder.setInsertable( columns[0].isInsertable() );
binder.setUpdatable( columns[0].isUpdatable() );
}
binder.setPropertyAccessorName( inferredData.getDefaultAccess() );
binder.setAccessType( inferredData.getDefaultAccess() );
binder.setCascade( cascadeStrategy );
Property prop = binder.make();
//composite FK columns are in the same table so its OK
@ -2556,15 +2472,12 @@ public final class AnnotationBinder {
hibernateCascadeAnnotation.value();
if ( hibernateCascades != null && hibernateCascades.length > 0 ) {
for (CascadeType cascadeType : hibernateCascades) {
hibernateCascadeSet.add( cascadeType );
}
hibernateCascadeSet.addAll( Arrays.asList( hibernateCascades ) );
}
StringBuilder cascade = new StringBuilder();
Iterator<CascadeType> cascadeType = hibernateCascadeSet.iterator();
while ( cascadeType.hasNext() ) {
switch ( cascadeType.next() ) {
for ( CascadeType aHibernateCascadeSet : hibernateCascadeSet ) {
switch ( aHibernateCascadeSet ) {
case ALL:
cascade.append( "," ).append( "all" );
break;

View File

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

View File

@ -111,7 +111,7 @@ public class OneToOneSecondPass implements SecondPass {
binder.setName( propertyName );
binder.setValue( value );
binder.setCascade( cascadeStrategy );
binder.setPropertyAccessorName( inferredData.getDefaultAccess() );
binder.setAccessType( inferredData.getDefaultAccess() );
Property prop = binder.make();
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)
* @throws MappingException No getter or field found or wrong JavaBean spec usage
*/
String getDefaultAccess();
AccessType getDefaultAccess();
/**
* @return property name

View File

@ -23,8 +23,9 @@
*/
package org.hibernate.cfg;
import javax.persistence.Access;
import org.hibernate.MappingException;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
@ -37,7 +38,7 @@ import org.hibernate.annotations.common.reflection.XProperty;
* @author Paolo Perrotta
*/
public class PropertyInferredData implements PropertyData {
private final String defaultAccess;
private final AccessType defaultAccess;
private final XProperty property;
private final ReflectionManager reflectionManager;
@ -50,15 +51,45 @@ public class PropertyInferredData implements PropertyData {
public PropertyInferredData(XClass declaringClass, XProperty property, String propertyAccessor, ReflectionManager reflectionManager) {
this.declaringClass = declaringClass;
this.property = property;
this.defaultAccess = propertyAccessor;
this.defaultAccess = AccessType.getAccessStrategy( propertyAccessor );
this.reflectionManager = reflectionManager;
}
public String getDefaultAccess() throws MappingException {
// if(skip())
// return defaultAccess;
AccessType access = property.getAnnotation( AccessType.class );
return access != null ? access.value() : defaultAccess;
public AccessType getDefaultAccess() throws MappingException {
AccessType accessType = defaultAccess;
AccessType hibernateAccessType = AccessType.DEFAULT;
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 {

View File

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

View File

@ -43,7 +43,7 @@ public class WrappedInferredData implements PropertyData {
return wrappedInferredData.getClassOrElementName();
}
public String getDefaultAccess() {
public AccessType getDefaultAccess() {
return wrappedInferredData.getDefaultAccess();
}

View File

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

View File

@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.Access;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
@ -38,7 +39,6 @@ import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.MappingException;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@ -60,6 +60,7 @@ import org.hibernate.annotations.Tuplizers;
import org.hibernate.annotations.Where;
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotationBinder;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.Ejb3JoinColumn;
@ -99,7 +100,6 @@ public class EntityBinder {
private ExtendedMappings mappings;
private Logger log = LoggerFactory.getLogger( EntityBinder.class );
private String discriminatorValue = "";
private boolean isPropertyAnnotated = false;
private boolean dynamicInsert;
private boolean dynamicUpdate;
private boolean explicitHibernateEntityAnnotation;
@ -118,11 +118,7 @@ public class EntityBinder {
private InheritanceState inheritanceState;
private boolean ignoreIdAnnotations;
private boolean cacheLazyProperty;
private String propertyAccessor;
public boolean isPropertyAnnotated() {
return isPropertyAnnotated;
}
private AccessType propertyAccessor = AccessType.DEFAULT;
/**
* Use as a fake one for Collection of elements
@ -847,36 +843,41 @@ public class EntityBinder {
}
}
public void setPropertyAnnotated(boolean propertyAnnotated) {
this.isPropertyAnnotated = propertyAnnotated;
}
public String getPropertyAccessor() {
public AccessType getPropertyAccessor() {
return propertyAccessor;
}
public void setPropertyAccessor(String propertyAccessor) {
public void setPropertyAccessor(AccessType propertyAccessor) {
this.propertyAccessor = propertyAccessor;
}
public boolean isPropertyAnnotated(XAnnotatedElement element) {
AccessType access = element.getAnnotation( AccessType.class );
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 AccessType getPropertyAccessor(XAnnotatedElement element) {
AccessType accessType = propertyAccessor;
public String getPropertyAccessor(XAnnotatedElement element) {
AccessType access = element.getAnnotation( AccessType.class );
if ( access == null ) return propertyAccessor;
return access.value();
AccessType hibernateAccessType = null;
AccessType jpaAccessType = null;
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.MapKey;
import org.hibernate.annotations.MapKeyManyToMany;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.AnnotatedClassType;
import org.hibernate.cfg.AnnotationBinder;
import org.hibernate.cfg.BinderHelper;
@ -227,10 +228,10 @@ public class MapBinder extends CollectionBinder {
//boolean propertyAccess = embeddable == null || AccessType.PROPERTY.equals( embeddable.access() );
//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
Component component = AnnotationBinder.fillComponent(
holder, inferredData, isPropertyAnnotated, isPropertyAnnotated ? "property" : "field", true,
holder, inferredData, isPropertyAnnotated ? AccessType.PROPERTY : AccessType.FIELD, true,
entityBinder, false, false,
true, mappings, inheritanceStatePerClass
);

View File

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