HHH-4202 - Implement JPA 2.0 metamodel APIs

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17850 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2009-10-27 18:49:25 +00:00
parent 2176af1144
commit e229d0171a
3 changed files with 171 additions and 126 deletions

View File

@ -1,32 +1,37 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-parent</artifactId> <artifactId>hibernate-parent</artifactId>
<version>3.5.0-SNAPSHOT</version> <version>3.5.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath> <relativePath>../parent/pom.xml</relativePath>
</parent> </parent>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId> <artifactId>hibernate-entitymanager</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Hibernate Entitity Manager</name> <name>Hibernate Entitity Manager</name>
<description>Hibernate Entitity Manager</description> <description>Hibernate Entitity Manager</description>
<!-- Annotations and Commons-Annotations both use the ANN JIRA key --> <!-- Annotations and Commons-Annotations both use the ANN JIRA key -->
<issueManagement> <issueManagement>
<system>jira</system> <system>jira</system>
<url>http://opensource.atlassian.com/projects/hibernate/browse/ANN</url> <url>http://opensource.atlassian.com/projects/hibernate/browse/ANN</url>
</issueManagement> </issueManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>${project.groupId}</groupId>
<artifactId>hibernate-core</artifactId> <artifactId>hibernate-core</artifactId>
<version>${version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>${project.groupId}</groupId>
<artifactId>hibernate-annotations</artifactId> <artifactId>hibernate-annotations</artifactId>
<version>${version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cglib</groupId> <groupId>cglib</groupId>
@ -41,26 +46,41 @@
<artifactId>jpa-api</artifactId> <artifactId>jpa-api</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <!--
Only really needed for the antrun plugin defined below (which in turn is only really needed
to work around a missing feature on the compile plugin; lovely no?). However I have not
found a way to declare this dependency local to the antrun plugin and then reference it
from the <javac/>'s <classpath/> :(
-->
<groupId>${project.groupId}</groupId>
<artifactId>hibernate-jpamodelgen</artifactId> <artifactId>hibernate-jpamodelgen</artifactId>
<version>1.0.0-Alpha1-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
<scope>test</scope> <scope>test</scope>
<exclusions>
<exclusion>
<!-- Use the jpa-api defined here, crossing fingers they match up signature-wise -->
<groupId>org.hibernate.java-persistence</groupId>
<artifactId>jpa-api</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
</dependencies> </dependencies>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>${project.groupId}</groupId>
<artifactId>hibernate-core</artifactId> <artifactId>hibernate-core</artifactId>
<version>${version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>${project.groupId}</groupId>
<artifactId>hibernate-annotations</artifactId> <artifactId>hibernate-annotations</artifactId>
<version>${version}</version> <version>${project.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<build> <build>
<testResources> <testResources>
<testResource> <testResource>
@ -70,7 +90,7 @@
<testResource> <testResource>
<filtering>true</filtering> <filtering>true</filtering>
<directory>src/test/bundles</directory> <directory>src/test/bundles</directory>
<targetPath>../bundles</targetPath> <targetPath>../bundles</targetPath>
</testResource> </testResource>
</testResources> </testResources>
<plugins> <plugins>
@ -84,65 +104,21 @@
<configuration> <configuration>
<tasks> <tasks>
<echo>processing JPA annotations</echo> <echo>processing JPA annotations</echo>
<property name="target.dir" value="target/generated-jpamodel-classes"/> <property name="target.dir" value="${project.build.directory}/generated-src/jpamodelgen"/>
<mkdir dir="${target.dir}"/> <mkdir dir="${target.dir}"/>
<javac srcdir="src/test/java" destdir="${target.dir}" failonerror="false" excludes="test/**" fork="true" executable="${jdk16_home}/bin/javac" target="1.5"> <javac srcdir="${project.build.testSourceDirectory}"
destdir="${target.dir}"
failonerror="false"
fork="true"
executable="${jdk16_home}/bin/javac"
target="1.5">
<compilerarg value="-proc:only"/> <compilerarg value="-proc:only"/>
<classpath> <classpath>
<path refid="maven.test.classpath"/> <path refid="maven.test.classpath"/>
</classpath> </classpath>
</javac> </javac>
</tasks> </tasks>
<sourceRoot>generate</sourceRoot> <testSourceRoot>${project.build.directory}/generated-src/jpamodelgen</testSourceRoot>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>target/generated-jpamodel-classes</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>package-tests</id>
<phase>process-test-classes</phase>
<configuration>
<tasks>
<property name="package.dir" value="${basedir}/target/test-packages"/>
<property name="package.tmp.dir" value="${basedir}/target/tmp"/>
<property name="classes.dir" value="${project.build.directory}/test-classes"/>
<property name="testresources.dir" value="${basedir}/target/bundles"/>
<ant antfile="${basedir}/build.xml">
<target name="package"/>
</ant>
</tasks>
</configuration> </configuration>
<goals> <goals>
<goal>run</goal> <goal>run</goal>
@ -150,6 +126,29 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>package-tests</id>
<phase>process-test-classes</phase>
<configuration>
<tasks>
<property name="package.dir" value="${basedir}/target/test-packages" />
<property name="package.tmp.dir" value="${basedir}/target/tmp" />
<property name="classes.dir" value="${project.build.directory}/test-classes" />
<property name="testresources.dir" value="${basedir}/target/bundles" />
<ant antfile="${basedir}/build.xml">
<target name="package" />
</ant>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
@ -170,79 +169,77 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<forkMode>pertest</forkMode> <forkMode>pertest</forkMode>
<additionalClasspathElements> <additionalClasspathElements>
<additionalClasspathElement>${basedir}/target/test-packages/cfgxmlpar.par</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/cfgxmlpar.par</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/defaultpar.par</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/defaultpar.par</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/excludehbmpar.par</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/excludehbmpar.par</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/explicitpar.par</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/explicitpar.par</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/explodedpar.par</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/explodedpar.par</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/externaljar.jar</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/externaljar.jar</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/nesteddir.ear</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/nesteddir.ear</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/nestedjar.ear</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/nestedjar.ear</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/overridenpar.jar</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/overridenpar.jar</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/space par.par</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/space par.par</additionalClasspathElement>
<additionalClasspathElement>${basedir}/target/test-packages/war.war</additionalClasspathElement> <additionalClasspathElement>${basedir}/target/test-packages/war.war</additionalClasspathElement>
</additionalClasspathElements> </additionalClasspathElements>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<profiles> <profiles>
<profile> <profile>
<id>doc</id> <id>doc</id>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.jboss.maven.plugins</groupId> <groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId> <artifactId>maven-jdocbook-plugin</artifactId>
<version>2.2.0</version> <version>2.1.0</version>
<extensions>true</extensions> <extensions>true</extensions>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-jdocbook-style</artifactId> <artifactId>hibernate-jdocbook-style</artifactId>
<version>2.0.0</version> <version>1.0.2</version>
<type>jdocbook-style</type> <type>jdocbook-style</type>
</dependency> </dependency>
</dependencies> </dependencies>
<configuration> <configuration>
<sourceDocumentName>master.xml</sourceDocumentName> <sourceDocumentName>master.xml</sourceDocumentName>
<sourceDirectory>${basedir}/src/main/docbook</sourceDirectory> <sourceDirectory>${basedir}/src/main/docbook/en</sourceDirectory>
<masterTranslation>en</masterTranslation> <masterTranslation>en-US</masterTranslation>
<imageResource> <imageResource>
<directory>${basedir}/src/main/docbook/en/images</directory> <directory>${basedir}/src/main/docbook/en/images</directory>
</imageResource> </imageResource>
<formats> <formats>
<format> <format>
<formatName>pdf</formatName> <formatName>pdf</formatName>
<stylesheetResource>classpath:/xslt/org/hibernate/jdocbook/xslt/pdf.xsl</stylesheetResource> <stylesheetResource>classpath:/xslt/hibernate/pdf/main-pdf.xsl</stylesheetResource>
<finalName>hibernate_reference.pdf</finalName> <finalName>hibernate-validator-legacy-guide.pdf</finalName>
</format> </format>
<format> <format>
<formatName>html_single</formatName> <formatName>html_single</formatName>
<stylesheetResource>classpath:/xslt/org/hibernate/jdocbook/xslt/xhtml-single.xsl <stylesheetResource>classpath:/xslt/hibernate/html/main-single.xsl
</stylesheetResource> </stylesheetResource>
<finalName>index.html</finalName> <finalName>index.html</finalName>
</format> </format>
<format> <format>
<formatName>html</formatName> <formatName>html</formatName>
<stylesheetResource>classpath:/xslt/org/hibernate/jdocbook/xslt/xhtml.xsl <stylesheetResource>classpath:/xslt/hibernate/html/main-chunk.xsl
</stylesheetResource> </stylesheetResource>
<finalName>index.html</finalName> <finalName>index.html</finalName>
</format> </format>
</formats> </formats>
<options> <options>
<xincludeSupported>true</xincludeSupported> <xincludeSupported>true</xincludeSupported>
<xmlTransformerType>saxon</xmlTransformerType>
<!-- needed for uri-resolvers; can be ommitted if using 'current' uri scheme -->
<!-- could also locate the docbook dependency and inspect its version... -->
<docbookVersion>1.72.0</docbookVersion>
<localeSeparator>-</localeSeparator> <localeSeparator>-</localeSeparator>
<useRelativeImageUris>true</useRelativeImageUris>
</options> </options>
</configuration> </configuration>
<executions> <executions>
@ -259,5 +256,6 @@
</plugins> </plugins>
</build> </build>
</profile> </profile>
</profiles> </profiles>
</project> </project>

View File

@ -30,6 +30,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.MappedSuperclass;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
@ -40,6 +41,10 @@ import org.hibernate.engine.SessionFactoryImplementor;
* <p/> * <p/>
* This contextual information includes data needing to be processed in a second pass as well as * This contextual information includes data needing to be processed in a second pass as well as
* cross-references into the built metamodel classes. * cross-references into the built metamodel classes.
* <p/>
* At the end of the day, clients are interested in the {@link #getEntityTypeMap} and {@link #getEmbeddableTypeMap}
* results, which represent all the registered {@link #registerEntityType entities} and
* {@link #registerEmbeddedableType embeddabled} respectively.
* *
* @author Steve Ebersole * @author Steve Ebersole
* @author Emmanuel Bernard * @author Emmanuel Bernard
@ -65,6 +70,29 @@ class MetadataContext {
return sessionFactory; return sessionFactory;
} }
/**
* Retrieves the {@link Class java type} to {@link EntityType} map.
*
* @return The {@link Class java type} to {@link EntityType} map.
*/
public Map<Class<?>, EntityTypeImpl<?>> getEntityTypeMap() {
return Collections.unmodifiableMap( entityTypes );
}
public Map<Class<?>, EmbeddableTypeImpl<?>> getEmbeddableTypeMap() {
return Collections.unmodifiableMap( embeddables );
}
/*package*/ void registerEntityType(PersistentClass persistentClass, EntityTypeImpl<?> entityType) {
entityTypes.put( entityType.getBindableJavaType(), entityType );
entityTypesByEntityName.put( persistentClass.getEntityName(), entityType );
entityTypesByPersistentClass.put( persistentClass, entityType );
}
/*package*/ void registerEmbeddedableType(EmbeddableTypeImpl<?> embeddableType) {
embeddables.put( embeddableType.getJavaType(), embeddableType );
}
/** /**
* Given a Hibernate {@link PersistentClass}, locate the corresponding JPA {@link org.hibernate.type.EntityType} * Given a Hibernate {@link PersistentClass}, locate the corresponding JPA {@link org.hibernate.type.EntityType}
* implementation. May retur null if the given {@link PersistentClass} has not yet been processed. * implementation. May retur null if the given {@link PersistentClass} has not yet been processed.
@ -98,29 +126,6 @@ class MetadataContext {
return entityTypesByEntityName.get( entityName ); return entityTypesByEntityName.get( entityName );
} }
/**
* Retrieves the {@link Class java type} to {@link EntityType} map.
*
* @return The {@link Class java type} to {@link EntityType} map.
*/
public Map<Class<?>, EntityTypeImpl<?>> getEntityTypeMap() {
return Collections.unmodifiableMap( entityTypes );
}
/*package*/ void registerEntityType(PersistentClass persistentClass, EntityTypeImpl<?> entityType) {
entityTypes.put( entityType.getBindableJavaType(), entityType );
entityTypesByEntityName.put( persistentClass.getEntityName(), entityType );
entityTypesByPersistentClass.put( persistentClass, entityType );
}
/*package*/ void registerEmbeddedableType(EmbeddableTypeImpl<?> embeddableType) {
embeddables.put( embeddableType.getJavaType(), embeddableType );
}
public Map<Class<?>, EmbeddableTypeImpl<?>> getEmbeddableTypeMap() {
return Collections.unmodifiableMap( embeddables );
}
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public void wrapUp() { public void wrapUp() {
// IMPL NOTE : entityTypesByPersistentClass is a insertion-ordered map, where the insertion order // IMPL NOTE : entityTypesByPersistentClass is a insertion-ordered map, where the insertion order
@ -135,7 +140,7 @@ class MetadataContext {
entry.getValue().getBuilder().addAttribute( attribute ); entry.getValue().getBuilder().addAttribute( attribute );
} }
entry.getValue().lock(); entry.getValue().lock();
// todo : find the X_ style metamodel classes, if present, and inject populateStaticMetamodel( entry.getValue() );
} }
} }
@ -171,4 +176,34 @@ class MetadataContext {
return attributes; return attributes;
} }
private <X> void populateStaticMetamodel(AbstractManagedType<X> managedType) {
final Class<X> managedTypeClass = managedType.getJavaType();
final String metamodelClassName = managedTypeClass.getName() + "_";
try {
final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() );
// we found the class; so populate it...
registerAttributes( metamodelClass, managedType );
}
catch ( ClassNotFoundException ignore ) {
// nothing to do...
}
// todo : this does not account for @MappeSuperclass, mainly because this is not being tracked in our
// internal metamodel as populated from the annotatios properly
AbstractManagedType<? super X> superType = managedType.getSupertype();
if ( superType != null ) {
populateStaticMetamodel( superType );
}
}
private final Set<Class> processedMetamodelClasses = new HashSet<Class>();
private <X> void registerAttributes(Class metamodelClass, AbstractManagedType<X> managedType) {
if ( processedMetamodelClasses.add( metamodelClass ) ) {
return;
}
// push the attributes on to the metamodel class...
}
} }

View File

@ -29,6 +29,11 @@ import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join; import javax.persistence.criteria.Join;
import org.hibernate.ejb.test.TestCase; import org.hibernate.ejb.test.TestCase;
import org.hibernate.ejb.test.callbacks.VideoSystem;
import org.hibernate.ejb.test.callbacks.Television;
import org.hibernate.ejb.test.callbacks.RemoteControl;
import org.hibernate.ejb.test.inheritance.Fruit;
import org.hibernate.ejb.test.inheritance.Strawberry;
/** /**
* TODO : javadoc * TODO : javadoc
@ -41,7 +46,14 @@ public class CriteriaCompilingTest extends TestCase {
Customer.class, Customer.class,
Item.class, Item.class,
Order.class, Order.class,
Product.class Product.class,
// @Inheritance
Fruit.class,
Strawberry.class,
// @MappedSuperclass
VideoSystem.class,
Television.class,
RemoteControl.class
}; };
} }