HHH-8247 Implement XML binding of NamedEntityGraph

This commit is contained in:
Strong Liu 2013-05-21 09:46:30 -07:00
parent 19da1ad211
commit 21444339ec
7 changed files with 240 additions and 10 deletions

View File

@ -25,6 +25,8 @@ package org.hibernate.cfg.annotations;
import javax.persistence.NamedEntityGraph;
import org.hibernate.internal.util.StringHelper;
/**
* Models the definition of a {@link NamedEntityGraph} annotation
*
@ -34,15 +36,17 @@ public class NamedEntityGraphDefinition {
private final NamedEntityGraph annotation;
private final String jpaEntityName;
private final String entityName;
private final String name;
public NamedEntityGraphDefinition(NamedEntityGraph annotation, String jpaEntityName, String entityName) {
this.annotation = annotation;
this.jpaEntityName = jpaEntityName;
this.entityName = entityName;
this.name = StringHelper.isEmpty( annotation.name() ) ? jpaEntityName : annotation.name();
}
public String getRegisteredName() {
return jpaEntityName;
return name;
}
public String getJpaEntityName() {

View File

@ -88,11 +88,16 @@ import javax.persistence.MapKeyJoinColumns;
import javax.persistence.MapKeyTemporal;
import javax.persistence.MappedSuperclass;
import javax.persistence.MapsId;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.NamedStoredProcedureQueries;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
@ -179,10 +184,14 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
annotationToXml.put( DiscriminatorColumn.class, "discriminator-column" );
annotationToXml.put( SequenceGenerator.class, "sequence-generator" );
annotationToXml.put( TableGenerator.class, "table-generator" );
annotationToXml.put( NamedEntityGraph.class, "named-entity-graph" );
annotationToXml.put( NamedEntityGraphs.class, "named-entity-graph" );
annotationToXml.put( NamedQuery.class, "named-query" );
annotationToXml.put( NamedQueries.class, "named-query" );
annotationToXml.put( NamedNativeQuery.class, "named-native-query" );
annotationToXml.put( NamedNativeQueries.class, "named-native-query" );
annotationToXml.put( NamedStoredProcedureQuery.class, "named-stored-procedure-query" );
annotationToXml.put( NamedStoredProcedureQueries.class, "named-stored-procedure-query" );
annotationToXml.put( SqlResultSetMapping.class, "sql-result-set-mapping" );
annotationToXml.put( SqlResultSetMappings.class, "sql-result-set-mapping" );
annotationToXml.put( ExcludeDefaultListeners.class, "exclude-default-listeners" );
@ -360,6 +369,8 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
addIfNotNull( annotationList, getTableGenerator( tree, defaults ) );
addIfNotNull( annotationList, getNamedQueries( tree, defaults ) );
addIfNotNull( annotationList, getNamedNativeQueries( tree, defaults ) );
addIfNotNull( annotationList, getNamedStoredProcedureQueries( tree, defaults ) );
addIfNotNull( annotationList, getNamedEntityGraphs( tree, defaults ) );
addIfNotNull( annotationList, getSqlResultSetMappings( tree, defaults ) );
addIfNotNull( annotationList, getExcludeDefaultListeners( tree, defaults ) );
addIfNotNull( annotationList, getExcludeSuperclassListeners( tree, defaults ) );
@ -1746,6 +1757,64 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
}
}
public static List<NamedEntityGraph> buildNamedEntityGraph(Element element, XMLContext.Default defaults) {
if ( element == null ) {
return new ArrayList<NamedEntityGraph>();
}
List<NamedEntityGraph> namedEntityGraphList = new ArrayList<NamedEntityGraph>();
List<Element> namedEntityGraphElements = element.elements( "named-entity-graph" );
for ( Element subElement : namedEntityGraphElements ) {
AnnotationDescriptor ann = new AnnotationDescriptor( NamedEntityGraph.class );
copyStringAttribute( ann, subElement, "name", false );
copyBooleanAttribute( ann, subElement, "include-all-attributes" );
bindNamedAttributeNodes( subElement, ann );
List<Element> subgraphNodes = subElement.elements( "subgraph" );
bindNamedSubgraph( defaults, ann, subgraphNodes );
List<Element> subclassSubgraphNodes = subElement.elements( "subclass-subgraph" );
bindNamedSubgraph( defaults, ann, subclassSubgraphNodes );
namedEntityGraphList.add( (NamedEntityGraph) AnnotationFactory.create( ann ) );
}
//TODO
return namedEntityGraphList;
}
private static void bindNamedSubgraph(XMLContext.Default defaults, AnnotationDescriptor ann, List<Element> subgraphNodes) {
List<NamedSubgraph> annSubgraphNodes = new ArrayList<NamedSubgraph>( );
for(Element subgraphNode : subgraphNodes){
AnnotationDescriptor annSubgraphNode = new AnnotationDescriptor( NamedSubgraph.class );
copyStringAttribute( annSubgraphNode, subgraphNode, "name", true );
String clazzName = subgraphNode.attributeValue( "class" );
Class clazz;
try {
clazz = ReflectHelper.classForName(
XMLContext.buildSafeClassName( clazzName, defaults ),
JPAOverriddenAnnotationReader.class
);
}
catch ( ClassNotFoundException e ) {
throw new AnnotationException( "Unable to find entity-class: " + clazzName, e );
}
annSubgraphNode.setValue( "type", clazz );
bindNamedAttributeNodes(subgraphNode, annSubgraphNode);
annSubgraphNodes.add( (NamedSubgraph) AnnotationFactory.create( annSubgraphNode ) );
}
ann.setValue( "subgraphs", annSubgraphNodes.toArray( new NamedSubgraph[annSubgraphNodes.size()] ) );
}
private static void bindNamedAttributeNodes(Element subElement, AnnotationDescriptor ann) {
List<Element> namedAttributeNodes = subElement.elements("named-attribute-node");
List<NamedAttributeNode> annNamedAttributeNodes = new ArrayList<NamedAttributeNode>( );
for(Element namedAttributeNode : namedAttributeNodes){
AnnotationDescriptor annNamedAttributeNode = new AnnotationDescriptor( NamedAttributeNode.class );
copyStringAttribute( annNamedAttributeNode, namedAttributeNode, "value", true );
copyStringAttribute( annNamedAttributeNode, namedAttributeNode, "subgraph", false );
copyStringAttribute( annNamedAttributeNode, namedAttributeNode, "key-subgraph", false );
annNamedAttributeNodes.add( (NamedAttributeNode) AnnotationFactory.create( annNamedAttributeNode ) );
}
ann.setValue( "attributeNodes", annNamedAttributeNodes.toArray( new NamedAttributeNode[annNamedAttributeNodes.size()] ) );
}
public static List<NamedStoredProcedureQuery> buildNamedStoreProcedureQueries(Element element, XMLContext.Default defaults) {
if ( element == null ) {
return new ArrayList<NamedStoredProcedureQuery>();
@ -1820,7 +1889,7 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
buildQueryHints( elements, ann );
namedStoredProcedureQueries.add( (NamedStoredProcedureQuery) AnnotationFactory.create( ann ) );
}
return namedStoredProcedureElements;
return namedStoredProcedureQueries;
}
@ -1953,6 +2022,84 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
}
}
private NamedEntityGraphs getNamedEntityGraphs(Element tree, XMLContext.Default defaults) {
List<NamedEntityGraph> queries = buildNamedEntityGraph( tree, defaults );
if ( defaults.canUseJavaAnnotations() ) {
NamedEntityGraph annotation = getJavaAnnotation( NamedEntityGraph.class );
addNamedEntityGraphIfNeeded( annotation, queries );
NamedEntityGraphs annotations = getJavaAnnotation( NamedEntityGraphs.class );
if ( annotations != null ) {
for ( NamedEntityGraph current : annotations.value() ) {
addNamedEntityGraphIfNeeded( current, queries );
}
}
}
if ( queries.size() > 0 ) {
AnnotationDescriptor ad = new AnnotationDescriptor( NamedEntityGraphs.class );
ad.setValue( "value", queries.toArray( new NamedEntityGraph[queries.size()] ) );
return AnnotationFactory.create( ad );
}
else {
return null;
}
}
private void addNamedEntityGraphIfNeeded(NamedEntityGraph annotation, List<NamedEntityGraph> queries) {
if ( annotation != null ) {
String queryName = annotation.name();
boolean present = false;
for ( NamedEntityGraph current : queries ) {
if ( current.name().equals( queryName ) ) {
present = true;
break;
}
}
if ( !present ) {
queries.add( annotation );
}
}
}
private NamedStoredProcedureQueries getNamedStoredProcedureQueries(Element tree, XMLContext.Default defaults) {
List<NamedStoredProcedureQuery> queries = buildNamedStoreProcedureQueries( tree, defaults );
if ( defaults.canUseJavaAnnotations() ) {
NamedStoredProcedureQuery annotation = getJavaAnnotation( NamedStoredProcedureQuery.class );
addNamedStoredProcedureQueryIfNeeded( annotation, queries );
NamedStoredProcedureQueries annotations = getJavaAnnotation( NamedStoredProcedureQueries.class );
if ( annotations != null ) {
for ( NamedStoredProcedureQuery current : annotations.value() ) {
addNamedStoredProcedureQueryIfNeeded( current, queries );
}
}
}
if ( queries.size() > 0 ) {
AnnotationDescriptor ad = new AnnotationDescriptor( NamedStoredProcedureQueries.class );
ad.setValue( "value", queries.toArray( new NamedStoredProcedureQuery[queries.size()] ) );
return AnnotationFactory.create( ad );
}
else {
return null;
}
}
private void addNamedStoredProcedureQueryIfNeeded(NamedStoredProcedureQuery annotation, List<NamedStoredProcedureQuery> queries) {
if ( annotation != null ) {
String queryName = annotation.name();
boolean present = false;
for ( NamedStoredProcedureQuery current : queries ) {
if ( current.name().equals( queryName ) ) {
present = true;
break;
}
}
if ( !present ) {
queries.add( annotation );
}
}
}
private NamedNativeQueries getNamedNativeQueries(Element tree, XMLContext.Default defaults) {
List<NamedNativeQuery> queries = (List<NamedNativeQuery>) buildNamedQueries( tree, true, defaults );
if ( defaults.canUseJavaAnnotations() ) {

View File

@ -34,12 +34,7 @@ import static junit.framework.Assert.assertNotNull;
/**
* @author Steve Ebersole
*/
public class BasicNamedEntityGraphTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Person.class };
}
public abstract class AbstractNamedEntityGraphTest extends BaseEntityManagerFunctionalTestCase {
@Test
public void testIt() {
EntityGraph graph = getOrCreateEntityManager().getEntityGraph( "Person" );

View File

@ -0,0 +1,35 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.jpa.test.graphs.named.basic;
/**
* @author Strong Liu <stliu@hibernate.org>
*/
public class BasicAnnNamedEntityGraphTest extends AbstractNamedEntityGraphTest{
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Person.class };
}
}

View File

@ -0,0 +1,34 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.jpa.test.graphs.named.basic;
/**
* @author Strong Liu <stliu@hibernate.org>
*/
public class BasicOrmNamedEntityGraphTest extends AbstractNamedEntityGraphTest{
@Override
public String[] getEjb3DD() {
return new String[]{"org/hibernate/jpa/test/graphs/named/basic/orm.xml"};
}
}

View File

@ -31,8 +31,8 @@ import javax.persistence.NamedEntityGraph;
* @author Steve Ebersole
*/
@Entity(name = "Person")
@NamedEntityGraph()
@NamedEntityGraph
public class Person {
@Id
private Long id;
public Long id;
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.1"
>
<package>org.hibernate.jpa.test.graphs.named.basic</package>
<entity class="Person" metadata-complete="true" access="FIELD">
<named-entity-graph/>
<attributes>
<id name="id">
<column name="fld_id"/>
</id>
</attributes>
</entity>
</entity-mappings>