2015-10-23 7 views
19

Mam moduł A i moduł B, które mają przypisane klasy JPA. Moduł B ma testów jednostkowych, które ciągnie się kilka tych podmiotów z A. Oba moduły skompilować porządku, Zależności uruchomieniowe są OK, ale pojawia się następujący komunikat o błędzie, gdy próbuję uruchomić test Jednostka:Jak skonfigurować hibernację do skanowania w poszukiwaniu obiektów w innym module?

java.lang.IllegalArgumentException: Unknown entity: MyClassHere 
Caused by: org.hibernate.MappingException: Unknown entity: MyClassHere 

To występuje w wywołaniu EntityManager.merge.

Ponieważ moduł B ma wszystkie pliki konfiguracyjne hibernacji itp., Domyślam się, że po prostu nie odbiera, że ​​moja klasa od A jest jednostką.

Próbowałem dodanie następujących do persistence.xml

<exclude-unlisted-classes>false</exclude-unlisted-classes> 

W hibernate.cfg.xml I dodaje:

<property name="packagesToScan">myNamespace.*</property> 

Następnie:

<property name="packagesToScan"> 
       <array> 
        <value>myNamespace.*</value> 
       </array> 
</property> 

To dało mi błąd treść "właściwości" musi być równa zeru. Następnie próbowałem:

<mapping class="myNamespace.*" /> 

Czego mi brakuje?

Edit: Jedną rzeczą, że zapomniałem wspomnieć, że może być bez znaczenia jest to, że oba moduły są skonfigurowane jako oddzielne projekty (używam zaćmienie), więc struktura katalogów jest inny. Zależności czasu działania są poprawnie skonfigurowane, ale ponieważ pliki .class znajdują się w różnych katalogach, myślę, że hibernacja może ich nie skanować.

+2

Używasz Spring? Mam podobną konfigurację, która działa za pomocą [setPackagesToScan] (http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html# setPackagesToScan-java.lang.String ...-) zastąpione w [LocalContainerEntityManagerFactoryBean] (http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean .html). –

+2

Czy możesz spróbować z ' myNamespace' (tj. Bez '. *'): Ta właściwość powinna wskazywać na pakiet macierzysty klas do skanowania. Na przykład. jeśli klasa 'MyEntity' znajduje się w pakiecie' my.package.MyEntity', napiszemy ' my.package' – Tunaki

+0

Wypróbowałem, to nie działało ... – ventsyv

Odpowiedz

1

Po skonfigurowaniu projektu do automatycznego wykrywania encji skanuje on tylko ścieżkę, w której znajduje się plik META-INF/persistence.xml (domyślnie).

Oprócz:

<exclude-unlisted-classes>false</exclude-unlisted-classes> 

ustawić dodatkową opcję Hibernacja:

<property name="hibernate.archive.autodetection" value="class, hbm" /> 

stwierdzi, który element jest auto odkryta przez Hibernate Entity Manager.

Do dodatkowych jednostek (w innych słoikach), można ustawić jar-pliku rozdział w swoim głównym pliku persistence.xml:

<persistence> 
    <persistence-unit name="myUnit"> 
     ... 
     <class>foo.bar.Entity1</class> 
     <class>foo.bar.Entity2</class> 
     <jar-file>moduleB.jar</jar-file> 
     ... 
    </persistence-unit> 
</persistence> 

Słoik-file element określa pliki JAR, które są widoczne na pakowana jednostka utrwalania, która zawiera zarządzane klasy utrwalania, podczas gdy element klasy jawnie nazywa zarządzane klasy trwałości.

Plik JAR lub katalog, którego katalog META-INF zawiera plik persistence.xml, jest nazywany korzeniem jednostki trwałości. Zakres jednostki trwałości jest określany przez root jednostki trwałości. Każda jednostka trwałości musi być identyfikowana przy użyciu nazwy, która jest unikalna dla zakresu jednostki utrwalania.

Pozdrawiam Andre

+1

Zgodnie z dokumentacją, klasa, hbm jest wartością domyślną dla tego ustawienia. Mimo to spróbowałem i nic się nie zmieniło. – ventsyv

0

persistence.xml mogą zawierać <jar-file>....jar</jar-file> elementu Określa jeden lub więcej plików JAR, które będą wyszukiwane w klasach.

0

Rozwiązaliśmy podobny problem w projekcie, nad którym pracuję, używając Spring do wykrywania obiektów. Na przykład. stosując uwagami konfigurację wiosny:

@Configuration 
@ComponentScan("com.org.prj.myNamespace1", "com.org.prj.myNamespace2") 
public class MyDatabaseConfig { 
    @Bean 
    public EntityManagerFactory entityManagerFactory() { 
     final LocalContainerEntityManagerFactoryBean factory = 
      new LocalContainerEntityManagerFactoryBean(); 

     // ...JPA properties, vendor adaptor, dialect, data source, persistence unit etc... 

     factory.setPackagesToScan("com.org.prj.myNamespace1", "com.org.prj.myNamespace2"); 

     factory.afterPropertiesSet(); 
     return factory.getObject(); 
    } 

    // ...Data source beans etc... 
} 
0

ja niedawno rozwiązać podobny problem, dodając ścieżkę do pliku jar persistence.xml

<jar-file>file:///C:/yourpath/yourJar.jar</jar-file>

Nadzieję, że to pomaga.  

2
  • Jeśli używasz hibernacji/wiosna możemy przedłużyć LocalSessionFactoryBean obiekt i skanować za pośrednictwem projektu zidentyfikować podmiot klas w projekcie.
  • Ponieważ mówisz o dwóch różnych projektach, spróbuj zapisać narzędzie do budowania czasu, aby przeanalizować dwa projekty i utworzyć jeden plik encji jednostki xml , który rozwiąże problem.
-1
  • src/main/resources: applicationContext.xml
  • src/test/Zasoby: test-applicationContext.xml

Upewnij w badanej zakresem również tworzyć swoje application- kontekst, aby wyszukać te elementy. Twój test-applicationContext.xml może nie konfigurować całego kontekstu aplikacji w czasie wykonywania, ale niektóre rzeczy, które są również potrzebne w czasie testu, powinny również zostać włączone, na przykład skanowanie twojego pakietu.

Można oczywiście stworzyć persistence.xml w src/main/zasobów i umieścić go w obu applicationContext.xml i test-applicationContext.xml

0

Prostym sposobem na to

configuration.addAnnotatedClass(Contact.class) 

jeśli chcesz użyć skanowania za pomocą pakietu, najpierw załaduj wszystkie klasy, używając ClassLoader. Zobacz przykładowy kod źródłowy z Hibernate-orm LocalSessionFactoryBuilder.class

@Bean 
public SessionFactory sessionFactory(){ 

    HibernateConfig configuration = new HibernateConfig(); 

    Properties properties = hibernateProperties(); 

    configuration.setProperties(properties); 

    configuration.scanPackages("com.atcc.stom.model.entity"); 

    return configuration.buildSessionFactory(); 
} 

HibernateConfig.class

import org.hibernate.HibernateException; 
import org.hibernate.MappingException; 
import org.hibernate.cfg.Configuration; 
import org.springframework.core.io.Resource; 
import org.springframework.core.io.ResourceLoader; 
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 
import org.springframework.core.io.support.ResourcePatternResolver; 
import org.springframework.core.io.support.ResourcePatternUtils; 
import org.springframework.core.type.classreading.CachingMetadataReaderFactory; 
import org.springframework.core.type.classreading.MetadataReader; 
import org.springframework.core.type.classreading.MetadataReaderFactory; 
import org.springframework.core.type.filter.AnnotationTypeFilter; 
import org.springframework.core.type.filter.TypeFilter; 
import org.springframework.util.ClassUtils; 

import javax.persistence.AttributeConverter; 
import javax.persistence.Embeddable; 
import javax.persistence.Entity; 
import javax.persistence.MappedSuperclass; 
import java.io.IOException; 
import java.lang.annotation.Annotation; 
import java.util.Set; 
import java.util.TreeSet; 

public class HibernateConfig extends Configuration { 

    private static final TypeFilter[] DEFAULT_ENTITY_TYPE_FILTERS = new TypeFilter[] { 
      new AnnotationTypeFilter(Entity.class, false), 
      new AnnotationTypeFilter(Embeddable.class, false), 
      new AnnotationTypeFilter(MappedSuperclass.class, false)}; 

    private static final String RESOURCE_PATTERN = "/**/*.class"; 

    private static final String PACKAGE_INFO_SUFFIX = ".package-info"; 

    private final ResourcePatternResolver resourcePatternResolver; 

    private static TypeFilter converterTypeFilter; 

    static { 
     try { 
      @SuppressWarnings("unchecked") 
      Class<? extends Annotation> converterAnnotation = (Class<? extends Annotation>) 
        ClassUtils.forName("javax.persistence.Converter", Configuration.class.getClassLoader()); 
      converterTypeFilter = new AnnotationTypeFilter(converterAnnotation, false); 
     } 
     catch (ClassNotFoundException ex) { 
      // JPA 2.1 API not available - Hibernate <4.3 
     } 
    } 

    public HibernateConfig() { 
     this(new PathMatchingResourcePatternResolver()); 
    } 

    public HibernateConfig(ClassLoader classLoader) { 
     this(new PathMatchingResourcePatternResolver(classLoader)); 
    } 

    public HibernateConfig(ResourceLoader resourceLoader) { 
     this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader); 
    } 

    public void scanPackages(String... packagesToScan) throws HibernateException { 
     Set<String> entityClassNames = new TreeSet<String>(); 
     Set<String> converterClassNames = new TreeSet<String>(); 
     Set<String> packageNames = new TreeSet<String>(); 
     try { 
      for (String pkg : packagesToScan) { 
       String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + 
         ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN; 

       Resource[] resources = this.resourcePatternResolver.getResources(pattern); 
       MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); 
       for (Resource resource : resources) { 
        if (resource.isReadable()) { 
         MetadataReader reader = readerFactory.getMetadataReader(resource); 
         String className = reader.getClassMetadata().getClassName(); 
         if (matchesEntityTypeFilter(reader, readerFactory)) { 
          entityClassNames.add(className); 
         } 
         else if (converterTypeFilter != null && converterTypeFilter.match(reader, readerFactory)) { 
          converterClassNames.add(className); 
         } 
         else if (className.endsWith(PACKAGE_INFO_SUFFIX)) { 
          packageNames.add(className.substring(0, className.length() - PACKAGE_INFO_SUFFIX.length())); 
         } 
        } 
       } 
      } 
     } 
     catch (IOException ex) { 
      throw new MappingException("Failed to scan classpath for unlisted classes", ex); 
     } 
     try { 
      ClassLoader cl = this.resourcePatternResolver.getClassLoader(); 
      for (String className : entityClassNames) { 
       addAnnotatedClass(cl.loadClass(className)); 
      } 
      for (String className : converterClassNames) { 
       ConverterRegistrationDelegate.registerConverter(this, cl.loadClass(className)); 
      } 
      for (String packageName : packageNames) { 
       addPackage(packageName); 
      } 
     } 
     catch (ClassNotFoundException ex) { 
      throw new MappingException("Failed to load annotated classes from classpath", ex); 
     } 
    } 

    private boolean matchesEntityTypeFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException { 
     for (TypeFilter filter : DEFAULT_ENTITY_TYPE_FILTERS) { 
      if (filter.match(reader, readerFactory)) { 
       return true; 
      } 
     } 
     return false; 
    } 

    /** 
    * Inner class to avoid hard dependency on JPA 2.1/Hibernate 4.3. 
    */ 
    private static class ConverterRegistrationDelegate { 

     @SuppressWarnings("unchecked") 
     public static void registerConverter(Configuration config, Class<?> converterClass) { 
      config.addAttributeConverter((Class<? extends AttributeConverter<?, ?>>) converterClass); 
     } 
    } 

} 
Powiązane problemy