Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the compiler doesn't recognize the metamodel attributes?

Is the criteria api of eclipselink jpa2 supported for java se 6 projects? If not, that's my problem. Do I need to specify anything special to the criteria api in the persistence.xml?

This is my criteria query:

 final EntityType<Meaning> Meaning_ = em.getMetamodel().entity(Meaning.class);
    final CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Integer> cq = cb.createQuery(Integer.class);
    final Root<Meaning> meng = cq.from(Meaning.class);
    cq.where(meng.get(Meaning_.lastPublishedDate)); //this attributes are not recognized/found
    cq.select(meng.get(Meaning_.objId));            // "                "                   
    TypedQuery<Integer> q = em.createQuery(cq); 
    return q.getResultList();

And here is my Meaning entity:

@Entity
public class Meaning implements Serializable{
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int objId;

public int getObjId() {
    return objId;
}

@Temporal(javax.persistence.TemporalType.DATE)
private Date lastPublishedDate = null;//never

public Date getLastPublishedDate(){
        return lastPublishedDate;
    }
}
like image 474
simpatico Avatar asked Aug 11 '10 13:08

simpatico


People also ask

What is metamodel in Java?

The Metamodel API is used to create a metamodel of the managed entities in a particular persistence unit. For each entity class in a particular package, a metamodel class is created with a trailing underscore and with attributes that correspond to the persistent fields or properties of the entity class.

What is static metamodel?

Hibernate Static Metamodel Generator is an annotation processor based on JSR_269 with the task of creating JPA 2 static metamodel classes. The following example shows two JPA 2 entities Order and Item, together with the metamodel class Order_ and a typesafe query. Example 1. JPA 2 annotated entities Order and Item.


2 Answers

About your code

I didn't check the correctness of the criteria query itself but, as Chris mentioned, you are mixing static metamodel classes with the EntityType that doesn't expose what you're looking for. Assuming your metamodel classes have been generated, remove the first line and import the generated Meaning_:

// final EntityType<Meaning> Meaning_ = em.getMetamodel().entity(Meaning.class); 
final CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Integer> cq = cb.createQuery(Integer.class);
final Root<Meaning> meng = cq.from(Meaning.class);
cq.where(meng.get(Meaning_.lastPublishedDate)); // add the appropriate import 
cq.select(meng.get(Meaning_.objId));            
TypedQuery<Integer> q = em.createQuery(cq); 
return q.getResultList();

About generation of the static (canonical) metamodel classes

Here is the Maven setup I'm using to generate the canonical metamodel classes with EclipseLink:

<project>
  ...
  <repositories>
    <!-- Repository for EclipseLink artifacts -->
    <repository>
      <id>EclipseLink Repo</id>
      <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo/</url>
    </repository>    
    ...
  </repositories>
  ...
  <pluginRepositories>
    <!-- For the annotation processor plugin -->
    <pluginRepository>
      <id>maven-annotation-plugin</id>
      <url>http://maven-annotation-plugin.googlecode.com/svn/trunk/mavenrepo</url>
    </pluginRepository>
  </pluginRepositories>
  ...
  <dependencies>
    <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>eclipselink</artifactId>
      <version>2.1.0</version>
    </dependency>
    <!-- optional - only needed if you are using JPA outside of a Java EE container-->
    <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>javax.persistence</artifactId>
      <version>2.0.2</version>
    </dependency>
  <dependencies>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.bsc.maven</groupId>
        <artifactId>maven-processor-plugin</artifactId>
        <version>1.3.1</version>
        <executions>
          <execution>
            <id>process</id>
            <goals>
              <goal>process</goal>
            </goals>
            <phase>generate-sources</phase>
            <configuration>
              <!-- Without this, the annotation processor complains about persistence.xml not being present and fail -->
              <compilerArguments>-Aeclipselink.persistencexml=src/main/resources/META-INF/persistence.xml</compilerArguments>
              <!-- For an unknown reason, the annotation processor is not discovered, have to list it explicitly -->
              <processors>
                <processor>org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor</processor>
              </processors>
              <!-- source output directory -->
              <outputDirectory>${project.build.directory}/generated-sources/meta-model</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <inherited>true</inherited>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
          <compilerArgument>-proc:none</compilerArgument>
        </configuration>
      </plugin>
      ...
    </plugins>
  </build>
</project>

Some comments:

  • EclipseLink annotation processor is provided by the main artifact, there is no extra dependency to add.
  • For an unknown reason, the annotation processor is not discovered, I have to list it explicitly as a <processor>.
  • Without the -Aeclipselink.persistencexml, the annotation processor complains about the persistence.xml not being present and fail.
  • I prefer to generate source code under target (I want a clean to clean it).

With this configuration, the static metamodel classes get generated and compiled appropriately.

like image 74
Pascal Thivent Avatar answered Sep 22 '22 18:09

Pascal Thivent


Looks like you are mixing static metamodel classes with the EntityType class. The EntityType will not have any of your metamodel's attributes on it - you will have to access them using the getSingularAttribute and getCollection methods i.e.:

meng.get(Meaning_.getSingularAttribute("someString", String.class))

Or you can use a static metamodel directly, but you will have to create the _ classes manually or use a generator as described at http://wiki.eclipse.org/UserGuide/JPA/Using_the_Canonical_Model_Generator_%28ELUG%29

like image 22
Chris Avatar answered Sep 23 '22 18:09

Chris