Added @FetchProfile and @FetchProfiles annotations and wired them up. Added also some error handling in the AnnotationBinder.
Refactor the handling of precedence in the AnnotationConfiguration, because I thought I would be reusing it for the fetch profile as well, but in the end decided to jsut implement in a way that xml configured fetch profiles always win over annotation confgured ones.


git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18924 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Hardy Ferentschik 2010-03-04 21:55:10 +00:00
parent 5b595bcf26
commit 153ad753e1
20 changed files with 1596 additions and 386 deletions

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.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Define the fetching strategy profile.
*
* @author Hardy Ferentschik
*/
@Target({ TYPE, PACKAGE })
@Retention(RUNTIME)
public @interface FetchProfile {
String name();
FetchOverride[] fetchOverrides();
@Target({ TYPE, PACKAGE })
@Retention(RUNTIME)
@interface FetchOverride {
Class<?> entity();
String association();
FetchMode mode();
}
}

View File

@ -0,0 +1,41 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @author Hardy Ferentschik
*/
@Target({ TYPE, PACKAGE })
@Retention(RUNTIME)
public @interface FetchProfiles {
public abstract FetchProfile[] value();
}

View File

@ -33,7 +33,9 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -55,10 +57,10 @@ import org.dom4j.Element;
import org.dom4j.io.SAXReader; import org.dom4j.io.SAXReader;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException; import org.xml.sax.SAXParseException;
import org.xml.sax.ErrorHandler;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.DuplicateMappingException; import org.hibernate.DuplicateMappingException;
@ -68,12 +70,12 @@ import org.hibernate.MappingException;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.annotations.AnyMetaDef; import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.Cache; import org.hibernate.annotations.Cache;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.annotations.common.reflection.MetadataProvider; import org.hibernate.annotations.common.reflection.MetadataProvider;
import org.hibernate.annotations.common.reflection.MetadataProviderInjector; import org.hibernate.annotations.common.reflection.MetadataProviderInjector;
import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.java.JavaReflectionManager; import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.cfg.annotations.Version; import org.hibernate.cfg.annotations.Version;
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider; import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
import org.hibernate.cfg.beanvalidation.BeanValidationActivator; import org.hibernate.cfg.beanvalidation.BeanValidationActivator;
@ -84,15 +86,16 @@ import org.hibernate.event.EventListeners;
import org.hibernate.event.PreInsertEventListener; import org.hibernate.event.PreInsertEventListener;
import org.hibernate.event.PreUpdateEventListener; import org.hibernate.event.PreUpdateEventListener;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
import org.hibernate.mapping.FetchProfile;
import org.hibernate.mapping.IdGenerator; import org.hibernate.mapping.IdGenerator;
import org.hibernate.mapping.Join; import org.hibernate.mapping.Join;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey; import org.hibernate.mapping.UniqueKey;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.JoinedIterator; import org.hibernate.util.JoinedIterator;
import org.hibernate.util.ReflectHelper; import org.hibernate.util.ReflectHelper;
import org.hibernate.util.StringHelper; import org.hibernate.util.StringHelper;
import org.hibernate.util.CollectionHelper;
/** /**
* Similar to the {@link Configuration} object but handles EJB3 and Hibernate * Similar to the {@link Configuration} object but handles EJB3 and Hibernate
@ -132,8 +135,9 @@ public class AnnotationConfiguration extends Configuration {
Version.touch(); //touch version Version.touch(); //touch version
} }
public static final String ARTEFACT = "hibernate.mapping.precedence"; public static final String ARTEFACT_PROCESSING_ORDER = "hibernate.mapping.precedence";
public static final String DEFAULT_PRECEDENCE = "hbm, class"; public static final ConfigurationArtefactType[] DEFAULT_ARTEFACT_PROCESSING_ORDER =
new ConfigurationArtefactType[] { ConfigurationArtefactType.HBM, ConfigurationArtefactType.CLASS };
private Map<String, IdGenerator> namedGenerators; private Map<String, IdGenerator> namedGenerators;
private Map<String, Map<String, Join>> joins; private Map<String, Map<String, Join>> joins;
@ -152,13 +156,13 @@ public class AnnotationConfiguration extends Configuration {
private Map<String, Document> hbmEntities; private Map<String, Document> hbmEntities;
private List<CacheHolder> caches; private List<CacheHolder> caches;
private List<Document> hbmDocuments; //user ordering matters, hence the list private List<Document> hbmDocuments; //user ordering matters, hence the list
private String precedence = null; private List<ConfigurationArtefactType> configurationArtefactPrecedence;
private boolean inSecondPass = false; private boolean inSecondPass = false;
private transient ReflectionManager reflectionManager; private transient ReflectionManager reflectionManager;
private boolean isDefaultProcessed = false; private boolean isDefaultProcessed = false;
private boolean isValidatorNotPresentLogged; private boolean isValidatorNotPresentLogged;
private Map<XClass,Map<String,PropertyData>> propertiesAnnotatedWithMapsId; private Map<XClass, Map<String, PropertyData>> propertiesAnnotatedWithMapsId;
private Map<XClass,Map<String,PropertyData>> propertiesAnnotatedWithIdAndToOne; private Map<XClass, Map<String, PropertyData>> propertiesAnnotatedWithIdAndToOne;
public AnnotationConfiguration() { public AnnotationConfiguration() {
super(); super();
@ -173,9 +177,10 @@ public class AnnotationConfiguration extends Configuration {
* ordered list. * ordered list.
* *
* @param original The list of all entities annotated with {@code @Entity} or {@code @MappedSuperclass} * @param original The list of all entities annotated with {@code @Entity} or {@code @MappedSuperclass}
*
* @return Ordered list of entities including superclasses for entities which have any. Class hierachies are * @return Ordered list of entities including superclasses for entities which have any. Class hierachies are
* listed bottom up (starting from the top level base class). There is no indication in the list when a new class * listed bottom up (starting from the top level base class). There is no indication in the list when a new class
* (hierarchy) starts. * (hierarchy) starts.
*/ */
protected List<XClass> orderAndFillHierarchy(List<XClass> original) { protected List<XClass> orderAndFillHierarchy(List<XClass> original) {
List<XClass> copy = new ArrayList<XClass>( original ); List<XClass> copy = new ArrayList<XClass>( original );
@ -226,6 +231,8 @@ public class AnnotationConfiguration extends Configuration {
* @param persistentClass the mapped class * @param persistentClass the mapped class
* *
* @return the configuration object * @return the configuration object
*
* @throws MappingException in case there is a configuration error for the specified class
*/ */
public AnnotationConfiguration addAnnotatedClass(Class persistentClass) throws MappingException { public AnnotationConfiguration addAnnotatedClass(Class persistentClass) throws MappingException {
XClass persistentXClass = reflectionManager.toXClass( persistentClass ); XClass persistentXClass = reflectionManager.toXClass( persistentClass );
@ -240,11 +247,13 @@ public class AnnotationConfiguration extends Configuration {
} }
/** /**
* Read package level metadata * Read package level metadata.
* *
* @param packageName java package name * @param packageName java package name
* *
* @return the configuration object * @return the configuration object
*
* @throws MappingException in case there is an error in the mapping data
*/ */
public AnnotationConfiguration addPackage(String packageName) throws MappingException { public AnnotationConfiguration addPackage(String packageName) throws MappingException {
log.info( "Mapping package {}", packageName ); log.info( "Mapping package {}", packageName );
@ -297,11 +306,11 @@ public class AnnotationConfiguration extends Configuration {
namingStrategy = EJB3NamingStrategy.INSTANCE; namingStrategy = EJB3NamingStrategy.INSTANCE;
setEntityResolver( new EJB3DTDEntityResolver() ); setEntityResolver( new EJB3DTDEntityResolver() );
anyMetaDefs = new HashMap<String, AnyMetaDef>(); anyMetaDefs = new HashMap<String, AnyMetaDef>();
propertiesAnnotatedWithMapsId = new HashMap<XClass, Map<String,PropertyData>>(); propertiesAnnotatedWithMapsId = new HashMap<XClass, Map<String, PropertyData>>();
propertiesAnnotatedWithIdAndToOne = new HashMap<XClass, Map<String,PropertyData>>(); propertiesAnnotatedWithIdAndToOne = new HashMap<XClass, Map<String, PropertyData>>();
reflectionManager = new JavaReflectionManager(); reflectionManager = new JavaReflectionManager();
( ( MetadataProviderInjector ) reflectionManager ).setMetadataProvider( new JPAMetadataProvider() ); ( ( MetadataProviderInjector ) reflectionManager ).setMetadataProvider( new JPAMetadataProvider() );
configurationArtefactPrecedence = Collections.emptyList();
} }
@Override @Override
@ -327,7 +336,7 @@ public class AnnotationConfiguration extends Configuration {
if ( !isDefaultProcessed ) { if ( !isDefaultProcessed ) {
//use global delimiters if orm.xml declare it //use global delimiters if orm.xml declare it
final Object isDelimited = reflectionManager.getDefaults().get( "delimited-identifier" ); final Object isDelimited = reflectionManager.getDefaults().get( "delimited-identifier" );
if (isDelimited != null && isDelimited == Boolean.TRUE) { if ( isDelimited != null && isDelimited == Boolean.TRUE ) {
getProperties().put( Environment.GLOBALLY_QUOTED_IDENTIFIERS, "true" ); getProperties().put( Environment.GLOBALLY_QUOTED_IDENTIFIERS, "true" );
} }
@ -336,20 +345,18 @@ public class AnnotationConfiguration extends Configuration {
} }
//process entities //process entities
if ( precedence == null ) { if ( configurationArtefactPrecedence.isEmpty()
precedence = getProperties().getProperty( ARTEFACT ); && StringHelper.isNotEmpty( getProperties().getProperty( ARTEFACT_PROCESSING_ORDER ) ) ) {
configurationArtefactPrecedence = parsePrecedence( getProperties().getProperty( ARTEFACT_PROCESSING_ORDER ) );
} }
if ( precedence == null ) { if ( configurationArtefactPrecedence.isEmpty() ) {
precedence = DEFAULT_PRECEDENCE; configurationArtefactPrecedence = Arrays.asList( DEFAULT_ARTEFACT_PROCESSING_ORDER );
} }
StringTokenizer precedences = new StringTokenizer( precedence, ",; ", false ); configurationArtefactPrecedence = Collections.unmodifiableList( configurationArtefactPrecedence );
if ( !precedences.hasMoreElements() ) {
throw new MappingException( ARTEFACT + " cannot be empty: " + precedence ); for ( ConfigurationArtefactType p : configurationArtefactPrecedence ) {
} removeConflictedArtifact( p );
while ( precedences.hasMoreElements() ) { processArtifactsOfType( p );
String artifact = ( String ) precedences.nextElement();
removeConflictedArtifact( artifact );
processArtifactsOfType( artifact );
} }
int cacheNbr = caches.size(); int cacheNbr = caches.size();
@ -381,11 +388,9 @@ public class AnnotationConfiguration extends Configuration {
throw ( RuntimeException ) e.getCause(); throw ( RuntimeException ) e.getCause();
} }
Iterator<Map.Entry<Table,List<UniqueConstraintHolder>>> tables = uniqueConstraintHoldersByTable.entrySet().iterator(); for ( Map.Entry<Table, List<UniqueConstraintHolder>> tableListEntry : uniqueConstraintHoldersByTable.entrySet() ) {
while ( tables.hasNext() ) { final Table table = tableListEntry.getKey();
final Map.Entry<Table,List<UniqueConstraintHolder>> entry = tables.next(); final List<UniqueConstraintHolder> uniqueConstraints = tableListEntry.getValue();
final Table table = entry.getKey();
final List<UniqueConstraintHolder> uniqueConstraints = entry.getValue();
int uniqueIndexPerTable = 0; int uniqueIndexPerTable = 0;
for ( UniqueConstraintHolder holder : uniqueConstraints ) { for ( UniqueConstraintHolder holder : uniqueConstraints ) {
uniqueIndexPerTable++; uniqueIndexPerTable++;
@ -607,8 +612,8 @@ public class AnnotationConfiguration extends Configuration {
} }
} }
private void processArtifactsOfType(String artifact) { private void processArtifactsOfType(ConfigurationArtefactType p) {
if ( "hbm".equalsIgnoreCase( artifact ) ) { if ( ConfigurationArtefactType.HBM.equals( p ) ) {
log.debug( "Process hbm files" ); log.debug( "Process hbm files" );
for ( Document document : hbmDocuments ) { for ( Document document : hbmDocuments ) {
super.add( document ); super.add( document );
@ -616,7 +621,7 @@ public class AnnotationConfiguration extends Configuration {
hbmDocuments.clear(); hbmDocuments.clear();
hbmEntities.clear(); hbmEntities.clear();
} }
else if ( "class".equalsIgnoreCase( artifact ) ) { else if ( ConfigurationArtefactType.CLASS.equals( p ) ) {
log.debug( "Process annotated classes" ); log.debug( "Process annotated classes" );
//bind classes in the correct order calculating some inheritance state //bind classes in the correct order calculating some inheritance state
List<XClass> orderedClasses = orderAndFillHierarchy( annotatedClasses ); List<XClass> orderedClasses = orderAndFillHierarchy( annotatedClasses );
@ -633,13 +638,10 @@ public class AnnotationConfiguration extends Configuration {
annotatedClasses.clear(); annotatedClasses.clear();
annotatedClassEntities.clear(); annotatedClassEntities.clear();
} }
else {
log.warn( "Unknown artifact: {}", artifact );
}
} }
private void removeConflictedArtifact(String artifact) { private void removeConflictedArtifact(ConfigurationArtefactType p) {
if ( "hbm".equalsIgnoreCase( artifact ) ) { if ( ConfigurationArtefactType.HBM.equals( p ) ) {
for ( String entity : hbmEntities.keySet() ) { for ( String entity : hbmEntities.keySet() ) {
if ( annotatedClassEntities.containsKey( entity ) ) { if ( annotatedClassEntities.containsKey( entity ) ) {
annotatedClasses.remove( annotatedClassEntities.get( entity ) ); annotatedClasses.remove( annotatedClassEntities.get( entity ) );
@ -647,7 +649,7 @@ public class AnnotationConfiguration extends Configuration {
} }
} }
} }
else if ( "class".equalsIgnoreCase( artifact ) ) { else if ( ConfigurationArtefactType.CLASS.equals( p ) ) {
for ( String entity : annotatedClassEntities.keySet() ) { for ( String entity : annotatedClassEntities.keySet() ) {
if ( hbmEntities.containsKey( entity ) ) { if ( hbmEntities.containsKey( entity ) ) {
hbmDocuments.remove( hbmEntities.get( entity ) ); hbmDocuments.remove( hbmEntities.get( entity ) );
@ -832,23 +834,19 @@ public class AnnotationConfiguration extends Configuration {
} }
public void setPrecedence(String precedence) { public void setPrecedence(String precedence) {
this.precedence = precedence; this.configurationArtefactPrecedence = parsePrecedence( precedence );
} }
private static class CacheHolder { private List<ConfigurationArtefactType> parsePrecedence(String s) {
public CacheHolder(String role, String usage, String region, boolean isClass, boolean cacheLazy) { if ( StringHelper.isEmpty( s ) ) {
this.role = role; return Collections.emptyList();
this.usage = usage;
this.region = region;
this.isClass = isClass;
this.cacheLazy = cacheLazy;
} }
StringTokenizer precedences = new StringTokenizer( s, ",; ", false );
public String role; List<ConfigurationArtefactType> tmpPrecedences = new ArrayList<ConfigurationArtefactType>();
public String usage; while ( precedences.hasMoreElements() ) {
public String region; tmpPrecedences.add( ConfigurationArtefactType.parsePrecedence( ( String ) precedences.nextElement() ) );
public boolean isClass; }
public boolean cacheLazy; return tmpPrecedences;
} }
@Override @Override
@ -860,11 +858,11 @@ public class AnnotationConfiguration extends Configuration {
* - if it fails because of the version attribute mismatch, try and validate the document with orm_1_0.xsd * - if it fails because of the version attribute mismatch, try and validate the document with orm_1_0.xsd
*/ */
List<SAXParseException> errors = new ArrayList<SAXParseException>(); List<SAXParseException> errors = new ArrayList<SAXParseException>();
SAXReader saxReader = new SAXReader( ); SAXReader saxReader = new SAXReader();
saxReader.setEntityResolver( getEntityResolver() ); saxReader.setEntityResolver( getEntityResolver() );
saxReader.setErrorHandler( new ErrorLogger(errors) ); saxReader.setErrorHandler( new ErrorLogger( errors ) );
saxReader.setMergeAdjacentText(true); saxReader.setMergeAdjacentText( true );
saxReader.setValidation(true); saxReader.setValidation( true );
setValidationFor( saxReader, "orm_2_0.xsd" ); setValidationFor( saxReader, "orm_2_0.xsd" );
@ -880,7 +878,7 @@ public class AnnotationConfiguration extends Configuration {
if ( e.getCause() == null || !( throwable instanceof SAXParseException ) ) { if ( e.getCause() == null || !( throwable instanceof SAXParseException ) ) {
throw new MappingException( "Could not parse JPA mapping document", e ); throw new MappingException( "Could not parse JPA mapping document", e );
} }
errors.add( (SAXParseException) throwable ); errors.add( ( SAXParseException ) throwable );
} }
boolean isV1Schema = false; boolean isV1Schema = false;
@ -889,11 +887,11 @@ public class AnnotationConfiguration extends Configuration {
final String errorMessage = exception.getMessage(); final String errorMessage = exception.getMessage();
//does the error look like a schema mismatch? //does the error look like a schema mismatch?
isV1Schema = doc != null isV1Schema = doc != null
&& errorMessage.contains("1.0") && errorMessage.contains( "1.0" )
&& errorMessage.contains("2.0") && errorMessage.contains( "2.0" )
&& errorMessage.contains("version"); && errorMessage.contains( "version" );
} }
if (isV1Schema) { if ( isV1Schema ) {
//reparse with v1 //reparse with v1
errors.clear(); errors.clear();
setValidationFor( saxReader, "orm_1_0.xsd" ); setValidationFor( saxReader, "orm_1_0.xsd" );
@ -903,21 +901,21 @@ public class AnnotationConfiguration extends Configuration {
} }
catch ( DocumentException e ) { catch ( DocumentException e ) {
//oops asXML fails even if the core doc parses initially //oops asXML fails even if the core doc parses initially
throw new AssertionFailure("Error in DOM4J leads to a bug in Hibernate", e); throw new AssertionFailure( "Error in DOM4J leads to a bug in Hibernate", e );
} }
} }
if ( errors.size() != 0 ) { if ( errors.size() != 0 ) {
//report errors in exception //report errors in exception
StringBuilder errorMessage = new StringBuilder( ); StringBuilder errorMessage = new StringBuilder();
for (SAXParseException error : errors) { for ( SAXParseException error : errors ) {
errorMessage.append("Error parsing XML (line") errorMessage.append( "Error parsing XML (line" )
.append(error.getLineNumber()) .append( error.getLineNumber() )
.append(" : column ") .append( " : column " )
.append(error.getColumnNumber()) .append( error.getColumnNumber() )
.append("): ") .append( "): " )
.append(error.getMessage()) .append( error.getMessage() )
.append("\n"); .append( "\n" );
} }
throw new MappingException( "Invalid ORM mapping file.\n" + errorMessage.toString() ); throw new MappingException( "Invalid ORM mapping file.\n" + errorMessage.toString() );
} }
@ -934,25 +932,6 @@ public class AnnotationConfiguration extends Configuration {
} }
} }
private static class ErrorLogger implements ErrorHandler {
private List<SAXParseException> errors;
public ErrorLogger(List<SAXParseException> errors) {
this.errors = errors;
}
public void warning(SAXParseException exception) throws SAXException {
errors.add( exception );
}
public void error(SAXParseException exception) throws SAXException {
errors.add( exception );
}
public void fatalError(SAXParseException exception) throws SAXException {
}
}
private void setValidationFor(SAXReader saxReader, String xsd) { private void setValidationFor(SAXReader saxReader, String xsd) {
try { try {
saxReader.setFeature( "http://apache.org/xml/features/validation/schema", true ); saxReader.setFeature( "http://apache.org/xml/features/validation/schema", true );
@ -1267,11 +1246,19 @@ public class AnnotationConfiguration extends Configuration {
} }
//not a public API //not a public API
public ReflectionManager getReflectionManager() { public ReflectionManager getReflectionManager() {
return reflectionManager; return reflectionManager;
} }
protected class ExtendedMappingsImpl extends MappingsImpl implements ExtendedMappings { protected class ExtendedMappingsImpl extends MappingsImpl implements ExtendedMappings {
private Boolean useNewGeneratorMappings;
private Collection<FetchProfile> annotationConfiguredProfile;
public ExtendedMappingsImpl() {
annotationConfiguredProfile = new ArrayList<FetchProfile>();
}
public void addDefaultGenerator(IdGenerator generator) { public void addDefaultGenerator(IdGenerator generator) {
this.addGenerator( generator ); this.addGenerator( generator );
defaultNamedGenerators.add( generator.getName() ); defaultNamedGenerators.add( generator.getName() );
@ -1288,7 +1275,7 @@ public class AnnotationConfiguration extends Configuration {
public void addPropertyAnnotatedWithMapsId(XClass entityType, PropertyData property) { public void addPropertyAnnotatedWithMapsId(XClass entityType, PropertyData property) {
Map<String, PropertyData> map = propertiesAnnotatedWithMapsId.get( entityType ); Map<String, PropertyData> map = propertiesAnnotatedWithMapsId.get( entityType );
if (map == null) { if ( map == null ) {
map = new HashMap<String, PropertyData>(); map = new HashMap<String, PropertyData>();
propertiesAnnotatedWithMapsId.put( entityType, map ); propertiesAnnotatedWithMapsId.put( entityType, map );
} }
@ -1302,15 +1289,13 @@ public class AnnotationConfiguration extends Configuration {
public void addToOneAndIdProperty(XClass entityType, PropertyData property) { public void addToOneAndIdProperty(XClass entityType, PropertyData property) {
Map<String, PropertyData> map = propertiesAnnotatedWithIdAndToOne.get( entityType ); Map<String, PropertyData> map = propertiesAnnotatedWithIdAndToOne.get( entityType );
if (map == null) { if ( map == null ) {
map = new HashMap<String, PropertyData>(); map = new HashMap<String, PropertyData>();
propertiesAnnotatedWithIdAndToOne.put( entityType, map ); propertiesAnnotatedWithIdAndToOne.put( entityType, map );
} }
map.put( property.getPropertyName(), property ); map.put( property.getPropertyName(), property );
} }
private Boolean useNewGeneratorMappings;
@SuppressWarnings({ "UnnecessaryUnboxing" }) @SuppressWarnings({ "UnnecessaryUnboxing" })
public boolean useNewGeneratorMappings() { public boolean useNewGeneratorMappings() {
if ( useNewGeneratorMappings == null ) { if ( useNewGeneratorMappings == null ) {
@ -1382,6 +1367,7 @@ public class AnnotationConfiguration extends Configuration {
} }
//FIXME should be private but is part of the ExtendedMapping contract //FIXME should be private but is part of the ExtendedMapping contract
public AnnotatedClassType addClassType(XClass clazz) { public AnnotatedClassType addClassType(XClass clazz) {
AnnotatedClassType type; AnnotatedClassType type;
if ( clazz.isAnnotationPresent( Entity.class ) ) { if ( clazz.isAnnotationPresent( Entity.class ) ) {
@ -1420,16 +1406,10 @@ public class AnnotationConfiguration extends Configuration {
return deprecatedStructure; return deprecatedStructure;
} }
/**
* {@inheritDoc}
*/
public Map<Table, List<UniqueConstraintHolder>> getUniqueConstraintHoldersByTable() { public Map<Table, List<UniqueConstraintHolder>> getUniqueConstraintHoldersByTable() {
return uniqueConstraintHoldersByTable; return uniqueConstraintHoldersByTable;
} }
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public void addUniqueConstraints(Table table, List uniqueConstraints) { public void addUniqueConstraints(Table table, List uniqueConstraints) {
List<UniqueConstraintHolder> constraintHolders = new ArrayList<UniqueConstraintHolder>( List<UniqueConstraintHolder> constraintHolders = new ArrayList<UniqueConstraintHolder>(
@ -1437,7 +1417,7 @@ public class AnnotationConfiguration extends Configuration {
); );
int keyNameBase = determineCurrentNumberOfUniqueConstraintHolders( table ); int keyNameBase = determineCurrentNumberOfUniqueConstraintHolders( table );
for ( String[] columns : (List<String[]>)uniqueConstraints ) { for ( String[] columns : ( List<String[]> ) uniqueConstraints ) {
final String keyName = "key" + keyNameBase++; final String keyName = "key" + keyNameBase++;
constraintHolders.add( constraintHolders.add(
new UniqueConstraintHolder().setName( keyName ).setColumns( columns ) new UniqueConstraintHolder().setName( keyName ).setColumns( columns )
@ -1453,9 +1433,6 @@ public class AnnotationConfiguration extends Configuration {
: currentHolders.size(); : currentHolders.size();
} }
/**
* {@inheritDoc}
*/
public void addUniqueConstraintHolders(Table table, List<UniqueConstraintHolder> uniqueConstraintHolders) { public void addUniqueConstraintHolders(Table table, List<UniqueConstraintHolder> uniqueConstraintHolders) {
List<UniqueConstraintHolder> holderList = getUniqueConstraintHoldersByTable().get( table ); List<UniqueConstraintHolder> holderList = getUniqueConstraintHoldersByTable().get( table );
if ( holderList == null ) { if ( holderList == null ) {
@ -1550,5 +1527,54 @@ public class AnnotationConfiguration extends Configuration {
public AnyMetaDef getAnyMetaDef(String name) { public AnyMetaDef getAnyMetaDef(String name) {
return anyMetaDefs.get( name ); return anyMetaDefs.get( name );
} }
public void addAnnotationConfiguredFetchProfile(FetchProfile fetchProfile) {
annotationConfiguredProfile.add( fetchProfile );
}
public boolean containsAnnotationConfiguredFetchProfile(FetchProfile fetchProfile) {
for ( FetchProfile profile : annotationConfiguredProfile ) {
// we need reference equality there!!
if ( profile == fetchProfile ) {
return true;
}
}
return false;
}
}
private static class CacheHolder {
public CacheHolder(String role, String usage, String region, boolean isClass, boolean cacheLazy) {
this.role = role;
this.usage = usage;
this.region = region;
this.isClass = isClass;
this.cacheLazy = cacheLazy;
}
public String role;
public String usage;
public String region;
public boolean isClass;
public boolean cacheLazy;
}
private static class ErrorLogger implements ErrorHandler {
private List<SAXParseException> errors;
public ErrorLogger(List<SAXParseException> errors) {
this.errors = errors;
}
public void warning(SAXParseException exception) throws SAXException {
errors.add( exception );
}
public void error(SAXParseException exception) throws SAXException {
errors.add( exception );
}
public void fatalError(SAXParseException exception) throws SAXException {
}
} }
} }

View File

@ -0,0 +1,49 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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 org.hibernate.HibernateException;
/**
* @author Hardy Ferentschik
*/
public enum ConfigurationArtefactType {
HBM,
CLASS;
static ConfigurationArtefactType parsePrecedence(String s) {
if ( s.equalsIgnoreCase( "hbm" ) ) {
return HBM;
}
else if ( s.equalsIgnoreCase( "class" ) ) {
return CLASS;
}
else {
throw new HibernateException( "'" + s + "' - invalid value for precedence configuration." );
}
}
}

View File

@ -1,3 +1,4 @@
// $Id:$
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
@ -30,12 +31,12 @@ import java.util.Properties;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.annotations.AnyMetaDef; import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.engine.NamedQueryDefinition; import org.hibernate.engine.NamedQueryDefinition;
import org.hibernate.engine.NamedSQLQueryDefinition; import org.hibernate.engine.NamedSQLQueryDefinition;
import org.hibernate.engine.ResultSetMappingDefinition; import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.mapping.FetchProfile;
import org.hibernate.mapping.IdGenerator; import org.hibernate.mapping.IdGenerator;
import org.hibernate.mapping.Join; import org.hibernate.mapping.Join;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
@ -47,6 +48,7 @@ import org.hibernate.mapping.Table;
* at least for named generators * at least for named generators
* *
* @author Emmanuel Bernard * @author Emmanuel Bernard
* @author Hardy Ferentschik
*/ */
public interface ExtendedMappings extends Mappings { public interface ExtendedMappings extends Mappings {
@ -61,6 +63,7 @@ public interface ExtendedMappings extends Mappings {
* Retrieve the id-generator by name. * Retrieve the id-generator by name.
* *
* @param name The generator name. * @param name The generator name.
*
* @return The generator, or null. * @return The generator, or null.
*/ */
public IdGenerator getGenerator(String name); public IdGenerator getGenerator(String name);
@ -71,6 +74,7 @@ public interface ExtendedMappings extends Mappings {
* *
* @param name generator name * @param name generator name
* @param localGenerators local generators * @param localGenerators local generators
*
* @return the appropriate idgenerator or null if not found * @return the appropriate idgenerator or null if not found
*/ */
public IdGenerator getGenerator(String name, Map<String, IdGenerator> localGenerators); public IdGenerator getGenerator(String name, Map<String, IdGenerator> localGenerators);
@ -95,6 +99,7 @@ public interface ExtendedMappings extends Mappings {
* *
* @param name generator name * @param name generator name
* @param localGeneratorTables local generator tables * @param localGeneratorTables local generator tables
*
* @return The properties, or null. * @return The properties, or null.
*/ */
public Properties getGeneratorTableProperties(String name, Map<String, Properties> localGeneratorTables); public Properties getGeneratorTableProperties(String name, Map<String, Properties> localGeneratorTables);
@ -103,6 +108,7 @@ public interface ExtendedMappings extends Mappings {
* Retrieve join metadata for a particular persistent entity. * Retrieve join metadata for a particular persistent entity.
* *
* @param entityName The entity name * @param entityName The entity name
*
* @return The join metadata * @return The join metadata
*/ */
public Map<String, Join> getJoins(String entityName); public Map<String, Join> getJoins(String entityName);
@ -112,6 +118,7 @@ public interface ExtendedMappings extends Mappings {
* *
* @param persistentClass The persistent entity metadata. * @param persistentClass The persistent entity metadata.
* @param joins The join metadata to add. * @param joins The join metadata to add.
*
* @throws MappingException * @throws MappingException
*/ */
public void addJoins(PersistentClass persistentClass, Map<String, Join> joins); public void addJoins(PersistentClass persistentClass, Map<String, Join> joins);
@ -120,6 +127,7 @@ public interface ExtendedMappings extends Mappings {
* Get and maintain a cache of class type. * Get and maintain a cache of class type.
* *
* @param clazz The XClass mapping * @param clazz The XClass mapping
*
* @return The class type. * @return The class type.
*/ */
public AnnotatedClassType getClassType(XClass clazz); public AnnotatedClassType getClassType(XClass clazz);
@ -129,6 +137,7 @@ public interface ExtendedMappings extends Mappings {
* Add a class type. * Add a class type.
* *
* @param clazz The XClass mapping. * @param clazz The XClass mapping.
*
* @return The class type. * @return The class type.
*/ */
public AnnotatedClassType addClassType(XClass clazz); public AnnotatedClassType addClassType(XClass clazz);
@ -170,7 +179,7 @@ public interface ExtendedMappings extends Mappings {
public void addAnyMetaDef(AnyMetaDef defAnn) throws AnnotationException; public void addAnyMetaDef(AnyMetaDef defAnn) throws AnnotationException;
public AnyMetaDef getAnyMetaDef(String name); public AnyMetaDef getAnyMetaDef(String name);
public boolean isInSecondPass(); public boolean isInSecondPass();
/** /**
@ -196,4 +205,16 @@ public interface ExtendedMappings extends Mappings {
public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String propertyName); public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String propertyName);
void addToOneAndIdProperty(XClass entity, PropertyData property); void addToOneAndIdProperty(XClass entity, PropertyData property);
/**
* Add the specified profile to the list of fetch profiles configured via annotations.
*
* @param fetchProfile the fetch profile
*/
void addAnnotationConfiguredFetchProfile(FetchProfile fetchProfile);
/**
* @return {@true} if the provided fetch profile has been configured via xml, {@false otherwise}.
*/
boolean containsAnnotationConfiguredFetchProfile(FetchProfile fetchProfile);
} }

View File

@ -0,0 +1,73 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.Map;
import org.hibernate.MappingException;
import org.hibernate.annotations.FetchProfile;
import org.hibernate.mapping.PersistentClass;
/**
* @author Hardy Ferentschik
*/
public class VerifyFetchProfileReferenceSecondPass implements SecondPass {
private String fetchProfileName;
private FetchProfile.FetchOverride fetch;
private ExtendedMappings mappings;
public VerifyFetchProfileReferenceSecondPass(String fetchProfileName, FetchProfile.FetchOverride fetch, ExtendedMappings mappings) {
this.fetchProfileName = fetchProfileName;
this.fetch = fetch;
this.mappings = mappings;
}
public void doSecondPass(Map persistentClasses) throws MappingException {
org.hibernate.mapping.FetchProfile profile = mappings.findOrCreateFetchProfile( fetchProfileName );
if ( skipProfile( profile ) ) {
return;
}
PersistentClass clazz = mappings.getClass( fetch.entity().getName() );
// throws MappingException in case the property does not exist
clazz.getProperty( fetch.association() );
profile.addFetch(
fetch.entity().getName(), fetch.association(), fetch.mode().toString().toLowerCase()
);
}
private boolean skipProfile(org.hibernate.mapping.FetchProfile profile) {
if ( mappings.containsAnnotationConfiguredFetchProfile( profile ) ) {
return false;
}
// if there are fetches they must come from xml. If there are xml profiles the annotations get ignored
return !profile.getFetches().isEmpty();
}
}

View File

@ -36,7 +36,7 @@ public class ConfigurationTest extends junit.framework.TestCase {
AnnotationConfiguration cfg = new AnnotationConfiguration(); AnnotationConfiguration cfg = new AnnotationConfiguration();
cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" ); cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" );
cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" );
cfg.setProperty( AnnotationConfiguration.ARTEFACT, "class, whatever" ); cfg.setProperty( AnnotationConfiguration.ARTEFACT_PROCESSING_ORDER, "class" );
SessionFactory sf = cfg.buildSessionFactory(); SessionFactory sf = cfg.buildSessionFactory();
assertNotNull( sf ); assertNotNull( sf );
Session s = sf.openSession(); Session s = sf.openSession();
@ -85,7 +85,7 @@ public class ConfigurationTest extends junit.framework.TestCase {
AnnotationConfiguration cfg = new AnnotationConfiguration(); AnnotationConfiguration cfg = new AnnotationConfiguration();
cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" ); cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" );
cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" );
cfg.setProperty( AnnotationConfiguration.ARTEFACT, "class, hbm" ); cfg.setProperty( AnnotationConfiguration.ARTEFACT_PROCESSING_ORDER, "class, hbm" );
cfg.addAnnotatedClass( Boat.class ); cfg.addAnnotatedClass( Boat.class );
SessionFactory sf = cfg.buildSessionFactory(); SessionFactory sf = cfg.buildSessionFactory();
assertNotNull( sf ); assertNotNull( sf );

View File

@ -1,4 +1,4 @@
//$Id: // $Id:$
@AnyMetaDefs( @AnyMetaDefs(
@AnyMetaDef( name= "Property", metaType = "string", idType = "integer", @AnyMetaDef( name= "Property", metaType = "string", idType = "integer",
metaValues = { metaValues = {

View File

@ -0,0 +1,92 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.fetchprofile;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.FetchProfile;
/**
* @author Hardy Ferentschik
*/
@Entity
@FetchProfile(name = "customer-with-orders", fetchOverrides = {
@FetchProfile.FetchOverride(entity = Customer.class, association = "orders", mode = FetchMode.JOIN)
})
public class Customer {
@Id
@GeneratedValue
private long id;
private String name;
private long customerNumber;
@OneToMany
private Set<Order> orders;
@OneToMany
private Set<SupportTickets> tickets;
public long getCustomerNumber() {
return customerNumber;
}
public void setCustomerNumber(long customerNumber) {
this.customerNumber = customerNumber;
}
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;
}
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
}

View File

@ -0,0 +1,88 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.fetchprofile;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.FetchProfile;
/**
* @author Hardy Ferentschik
*/
@Entity
@FetchProfile(name = "customer-with-orders", fetchOverrides = {
@FetchProfile.FetchOverride(entity = Customer2.class, association = "foo", mode = FetchMode.JOIN)
})
public class Customer2 {
@Id
@GeneratedValue
private long id;
private String name;
private long customerNumber;
@OneToMany
private Set<Order> orders;
public long getCustomerNumber() {
return customerNumber;
}
public void setCustomerNumber(long customerNumber) {
this.customerNumber = customerNumber;
}
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;
}
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
}

View File

@ -0,0 +1,88 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.fetchprofile;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.FetchProfile;
/**
* @author Hardy Ferentschik
*/
@Entity
@FetchProfile(name = "wrong-class-name", fetchOverrides = {
@FetchProfile.FetchOverride(entity = Order.class, association = "orders", mode = FetchMode.JOIN)
})
public class Customer3 {
@Id
@GeneratedValue
private long id;
private String name;
private long customerNumber;
@OneToMany
private Set<Order> orders;
public long getCustomerNumber() {
return customerNumber;
}
public void setCustomerNumber(long customerNumber) {
this.customerNumber = customerNumber;
}
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;
}
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
}

View File

@ -0,0 +1,88 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.fetchprofile;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.FetchProfile;
/**
* @author Hardy Ferentschik
*/
@Entity
@FetchProfile(name = "unsupported-fetch-mode", fetchOverrides = {
@FetchProfile.FetchOverride(entity = Customer4.class, association = "orders", mode = FetchMode.SELECT)
})
public class Customer4 {
@Id
@GeneratedValue
private long id;
private String name;
private long customerNumber;
@OneToMany
private Set<Order> orders;
public long getCustomerNumber() {
return customerNumber;
}
public void setCustomerNumber(long customerNumber) {
this.customerNumber = customerNumber;
}
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;
}
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
}

View File

@ -0,0 +1,88 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.fetchprofile;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.FetchProfile;
/**
* @author Hardy Ferentschik
*/
@Entity
@FetchProfile(name = "orders-profile", fetchOverrides = {
@FetchProfile.FetchOverride(entity = Customer5.class, association = "foo", mode = FetchMode.JOIN)
})
public class Customer5 {
@Id
@GeneratedValue
private long id;
private String name;
private long customerNumber;
@OneToMany
private Set<Order> orders;
public long getCustomerNumber() {
return customerNumber;
}
public void setCustomerNumber(long customerNumber) {
this.customerNumber = customerNumber;
}
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;
}
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
}

View File

@ -0,0 +1,151 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.fetchprofile;
import java.io.InputStream;
import junit.framework.TestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.MappingException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.engine.SessionFactoryImplementor;
/**
* Test case for HHH-4812
*
* @author Hardy Ferentschik
*/
public class FetchProfileTest extends TestCase {
private Logger log = LoggerFactory.getLogger( FetchProfileTest.class );
public void testFetchProfileConfigured() {
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass( Customer.class );
config.addAnnotatedClass( Order.class );
config.addAnnotatedClass( SupportTickets.class );
SessionFactoryImplementor sessionImpl = ( SessionFactoryImplementor ) config.buildSessionFactory();
assertTrue(
"fetch profile not parsed properly",
sessionImpl.containsFetchProfileDefinition( "customer-with-orders" )
);
assertFalse(
"package info should not be parsed",
sessionImpl.containsFetchProfileDefinition( "package-profile-1" )
);
}
public void testWrongAssociationName() {
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass( Customer2.class );
config.addAnnotatedClass( Order.class );
try {
config.buildSessionFactory();
fail();
}
catch ( MappingException e ) {
log.trace( "success" );
}
}
public void testWrongClass() {
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass( Customer3.class );
config.addAnnotatedClass( Order.class );
try {
config.buildSessionFactory();
fail();
}
catch ( MappingException e ) {
log.trace( "success" );
}
}
public void testUnsupportedFetchMode() {
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass( Customer4.class );
config.addAnnotatedClass( Order.class );
try {
config.buildSessionFactory();
fail();
}
catch ( MappingException e ) {
log.trace( "success" );
}
}
public void testXmlOverride() {
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass( Customer5.class );
config.addAnnotatedClass( Order.class );
InputStream is = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream( "org/hibernate/test/annotations/fetchprofile/mappings.hbm.xml" );
config.addInputStream( is );
SessionFactoryImplementor sessionImpl = ( SessionFactoryImplementor ) config.buildSessionFactory();
assertTrue(
"fetch profile not parsed properly",
sessionImpl.containsFetchProfileDefinition( "orders-profile" )
);
// now the same with no xml
config = new AnnotationConfiguration();
config.addAnnotatedClass( Customer5.class );
config.addAnnotatedClass( Order.class );
try {
config.buildSessionFactory();
fail();
}
catch ( MappingException e ) {
log.trace( "success" );
}
}
public void testPackageConfiguredFetchProfile() {
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass( Customer.class );
config.addAnnotatedClass( Order.class );
config.addAnnotatedClass( SupportTickets.class );
config.addPackage( Customer.class.getPackage().getName() );
SessionFactoryImplementor sessionImpl = ( SessionFactoryImplementor ) config.buildSessionFactory();
assertTrue(
"fetch profile not parsed properly",
sessionImpl.containsFetchProfileDefinition( "package-profile-1" )
);
assertTrue(
"fetch profile not parsed properly",
sessionImpl.containsFetchProfileDefinition( "package-profile-2" )
);
}
}

View File

@ -0,0 +1,71 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.fetchprofile;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Order {
@Id
@GeneratedValue
private long id;
private long orderNumber;
private Date deliveryDate;
public Date getDeliveryDate() {
return deliveryDate;
}
public void setDeliveryDate(Date deliveryDate) {
this.deliveryDate = deliveryDate;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getOrderNumber() {
return orderNumber;
}
public void setOrderNumber(long orderNumber) {
this.orderNumber = orderNumber;
}
}

View File

@ -0,0 +1,70 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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.fetchprofile;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Hardy Ferentschik
*/
@Entity
public class SupportTickets {
@Id
@GeneratedValue
private long id;
private String description;
private String resolution;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getResolution() {
return resolution;
}
public void setResolution(String resolution) {
this.resolution = resolution;
}
}

View File

@ -0,0 +1,41 @@
// $Id:$
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, 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
*
*/
@FetchProfiles({
@FetchProfile(name = "package-profile-1", fetchOverrides = {
@FetchProfile.FetchOverride(entity = Customer.class, association = "orders", mode = FetchMode.JOIN)
}),
@FetchProfile(name = "package-profile-2", fetchOverrides = {
@FetchProfile.FetchOverride(entity = Customer.class, association = "tickets", mode = FetchMode.JOIN)
})
})
package org.hibernate.test.annotations.fetchprofile;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.FetchProfile;
import org.hibernate.annotations.FetchProfiles;

View File

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
SYSTEM
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<!--
~ 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
~
-->
<hibernate-mapping package="org.hibernate.test.annotations.fetchprofile">
<fetch-profile name="orders-profile">
<fetch entity="Customer5" association="orders" style="join"/>
</fetch-profile>
</hibernate-mapping>

View File

@ -65,7 +65,7 @@
<dependency> <dependency>
<groupId>org.jboss.shrinkwrap</groupId> <groupId>org.jboss.shrinkwrap</groupId>
<artifactId>shrinkwrap-impl-base</artifactId> <artifactId>shrinkwrap-impl-base</artifactId>
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-alpha-6</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>