Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Can't make @MappedSuperclass work with EclipseLink / Spring Data JPA
Can't make @MappedSuperclass work with EclipseLink / Spring Data JPA [message #986118] Sun, 18 November 2012 21:30 Go to previous message
Emmanuel Cron is currently offline Emmanuel Cron
Messages: 1
Registered: November 2012
Location: San Francisco
Junior Member
Hey guys,

So I've been working two days to make something work without success. My goal is fairly simple: make a JPA repository using Spring Data JPA and EclipseLink that is able to query a superclass element (named 'HelpElement') that is implemented by two actual database objects ('HelpTopic' and 'HelpPage').

So I have been reading the web. A lot. And I can't make it work. Important note: everything is working fine using only EclipseLink. As soon as I add Spring Data JPA, i get the following exception that I now dream of during my nightmares.

Caused by: java.lang.IllegalArgumentException: No [EntityType] was found for the key class [com.dalarian.db.entity.help.HelpElement] in the Metamodel - please verify that the [Entity] class was referenced in persistence.xml using a specific <class>com.dalarian.db.entity.help.HelpElement</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.


So here are all the files I use that should be required to see where I have done things wrong.

META-INF/persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="h t t p://java.sun.com/xml/ns/persistence" version="1.0">
  <persistence-unit name="default">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>com.dalarian.db.help.HelpTopic</class>
    <class>com.dalarian.db.help.HelpPage</class>
    <class>com.dalarian.db.help.HelpElement</class>
    <properties>
      <property name="eclipselink.logging.level" value="INFO"></property>
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"></property>
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://${database.server}:${database.port}/${database.db_name}"></property>
      <property name="javax.persistence.jdbc.password" value="${database.password}"></property>
      <property name="javax.persistence.jdbc.user" value="${database.user}"></property>
    </properties>
  </persistence-unit>
</persistence>


com.dalarian.ApplicationContext
package com.dalarian;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;

import javax.persistence.EntityManagerFactory;

/**
 * Core application global configuration.
 *
 */
@Configuration
@ComponentScan(basePackages = {"com.dalarian.db"})
@EnableJpaRepositories
public class ApplicationContext {
  @Bean
  public JpaVendorAdapter vendorAdapter() {
    EclipseLinkJpaVendorAdapter vendorAdapter = new EclipseLinkJpaVendorAdapter();
    vendorAdapter.setDatabasePlatform("org.eclipse.persistence.platform.database.MySQLPlatform");
    vendorAdapter.setShowSql(true);
    return vendorAdapter;
  }

//  @Bean
//  public DataSource dataSource() {
//    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
//    return builder.setType(EmbeddedDatabaseType.HSQL).build();
//  }

  @Bean
  public EntityManagerFactory entityManagerFactory() {
    EclipseLinkJpaVendorAdapter vendorAdapter = new EclipseLinkJpaVendorAdapter();
//    vendorAdapter.setGenerateDdl(true);
    vendorAdapter.setShowSql(true);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
//    factory.setPackagesToScan("com.acme.domain");
//    factory.setDataSource(dataSource());
    factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
    factory.afterPropertiesSet();

    return factory.getObject();
  }

  @Bean
  public PersistenceExceptionTranslator persistenceExceptionTranslator() {
    return new EclipseLinkJpaDialect();
  }
}


Database entities

com.dalarian.db.entity.help.HelpElement
package com.dalarian.db.entity.help;

import java.util.Set;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.TableGenerator;

@MappedSuperclass
public abstract class HelpElement implements Comparable<HelpElement> {
  @Id
  @GeneratedValue(generator="HelpElement")
  @TableGenerator(name="HelpElement", table="sequence",
    pkColumnName="Name", pkColumnValue="HelpElement",
    valueColumnName="Value", allocationSize=1)
  private long id;

  @Column(name="ParentID")
  private long parentId;

  @Column(name="Position")
  private int position;

  private transient Set<HelpElement> children;

  @Column(name="Title")
  private String title;

  public boolean isRoot() {
    return parentId < 1;
  }

  @Override
  public int compareTo(HelpElement o) {
    if (this.getParentId() != o.getParentId()) {
      throw new UnsupportedOperationException("Cannot compare two help elements belonging to two different parents");
    }

    int c = new Integer(this.getPosition()).compareTo(new Integer(o.getPosition()));
    if (c != 0) {
      return c;
    } else {
      return this.getTitle().compareTo(o.getTitle());
    }
  }

  // Getters and setters
  // ...
}


com.dalarian.db.entity.help.HelpTopic
package com.dalarian.db.entity.help;

import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="help_topic")
@AttributeOverride(name="id", column=@Column(name="HelpTopicID"))
public class HelpTopic extends HelpElement {
	
}


com.dalarian.db.entity.help.HelpPage
package com.dalarian.db.entity.help;

import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="help_page")
@AttributeOverride(name="id", column=@Column(name="HelpPageID"))
public class HelpPage extends HelpElement {
	@Column(name="Content")
	private String contents;

	public String getContents() {
		return contents;
	}

	public void setContents(String contents) {
		this.contents = contents;
	}
}


Repositories

com.dalarian.db.repository.HelpRepository
package com.dalarian.db.repository;

import com.dalarian.db.entity.help.HelpElement;

import org.springframework.data.repository.CrudRepository;

public interface HelpRepository extends CrudRepository<HelpElement, Long>, HelpRepositoryCustom {

}


com.dalarian.db.repository.HelpRepositoryCustom
package com.dalarian.db.repository;

import com.dalarian.db.entity.help.HelpElement;

import java.util.Set;

public interface HelpRepositoryCustom {
  public Set<HelpElement> findRootElements();
}


com.dalarian.db.repository.HelpRepositoryImpl
import com.dalarian.db.entity.help.HelpElement;

import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Set;
import java.util.TreeSet;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Repository
public class HelpRepositoryImpl implements HelpRepositoryCustom {

  @PersistenceContext
  private EntityManager entityManager;

  private SimpleJpaRepository<HelpElement, Long> helpRepository;

  @Override
  public Set<HelpElement> findRootElements() {
    Set<HelpElement> elements = new TreeSet<HelpElement>();
    for (HelpElement element : helpRepository.findAll()) {
      if (element.getParentId() == 0) {
        elements.add(element);
      }
    }
    return elements;
  }

  @PostConstruct
  public void init() {
    helpRepository = new SimpleJpaRepository<HelpElement, Long>(HelpElement.class, entityManager);
  }

}


Test class

Finally, this is the code I use to test my code using JUnit:
package com.dalarian.test.audit;

import com.dalarian.ApplicationContext;
import com.dalarian.db.entity.help.HelpElement;
import com.dalarian.db.repository.HelpRepository;

import org.apache.log4j.Logger;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public final class HelpAudit {
	private static final Logger LOG = Logger.getLogger(HelpAudit.class);

	private HelpAudit() {}

	public static void main(String[] args) {
	  AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationContext.class);
	  HelpRepository helpRepository = applicationContext.getBean(HelpRepository.class);
//	  HelpManager helpManager = applicationContext.getBean(HelpManager.class);
		for (HelpElement element : helpRepository.findRootElements()) {
			recursiveDisplay(element, "");
		}
	}

	private static void recursiveDisplay(HelpElement element, String prefix) {
		LOG.debug(prefix + element.getPosition() + ". " + element.getTitle());
		if (element.getChildren() != null) {
			for (HelpElement child : element.getChildren()) {
				recursiveDisplay(child, prefix + "\t");
			}
		}
	}
}


Resulting exception Sad

[EL Info]: 2012-11-18 18:23:09.215--ServerSession(51898531)--Thread(Thread[main,5,main])--EclipseLink, version: Eclipse Persistence Services - 2.4.0.v20120608-r11652
[EL Fine]: connection: 2012-11-18 18:23:09.441--Thread(Thread[main,5,main])--Detected database platform: org.eclipse.persistence.platform.database.MySQLPlatform
[EL Config]: connection: 2012-11-18 18:23:09.455--ServerSession(51898531)--Connection(1856697764)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
  platform=>MySQLPlatform
  user name=> "***"
  datasource URL=> "jdbc:mysql://localhost:3306/***"
))
[EL Config]: connection: 2012-11-18 18:23:09.466--ServerSession(51898531)--Connection(1575554065)--Thread(Thread[main,5,main])--Connected: jdbc:mysql://localhost:3306/***
  User: ***@***
  Database: MySQL  Version: 5.1.42-community
  Driver: MySQL-AB JDBC Driver  Version: mysql-connector-java-5.1.12 ( Revision: ${bzr.revision-id} )
[EL Info]: connection: 2012-11-18 18:23:09.555--ServerSession(51898531)--Thread(Thread[main,5,main])--file:/***/target/classes/_default login successful
Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: No [EntityType] was found for the key class [com.dalarian.db.entity.help.HelpElement] in the Metamodel - please verify that the [Entity] class was referenced in persistence.xml using a specific <class>com.dalarian.db.entity.help.HelpElement</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.; nested exception is java.lang.IllegalArgumentException: No [EntityType] was found for the key class [com.dalarian.db.entity.help.HelpElement] in the Metamodel - please verify that the [Entity] class was referenced in persistence.xml using a specific <class>com.dalarian.db.entity.help.HelpElement</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
  at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:301)
  at org.springframework.orm.jpa.DefaultJpaDialect.translateExceptionIfPossible(DefaultJpaDialect.java:120)
  at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
  at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
  at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
  at $Proxy16.findRootElements(Unknown Source)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:601)
  at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:334)
  at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:309)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
  at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
  at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
  at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:91)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
  at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
  at $Proxy19.findRootElements(Unknown Source)
  at com.dalarian.test.audit.HelpAudit.main(HelpAudit.java:22)
Caused by: java.lang.IllegalArgumentException: No [EntityType] was found for the key class [com.dalarian.db.entity.help.HelpElement] in the Metamodel - please verify that the [Entity] class was referenced in persistence.xml using a specific <class>com.dalarian.db.entity.help.HelpElement</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
  at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entityEmbeddableManagedTypeNotFound(MetamodelImpl.java:174)
  at org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl.entity(MetamodelImpl.java:194)
  at org.eclipse.persistence.internal.jpa.querydef.AbstractQueryImpl.from(AbstractQueryImpl.java:97)
  at org.springframework.data.jpa.repository.support.SimpleJpaRepository.applySpecificationToCriteria(SimpleJpaRepository.java:474)
  at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:437)
  at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:239)
  at com.dalarian.db.repository.HelpRepositoryImpl.findRootElements(HelpRepositoryImpl.java:33)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:601)
  at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
  at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
  ... 21 more


Sorry for the long post, but if anybody has an idea on how to fix that, I'd be glad!
 
Read Message
Read Message
Previous Topic:Persistence unit with entities in multiple jars and static weaving
Next Topic:Replication/union partitioning and elasticity
Goto Forum:
  


Current Time: Tue May 21 15:29:15 EDT 2013

Powered by FUDForum. Page generated in 0.03206 seconds