首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何配置hibernate以扫描不同模块中的实体

如何配置hibernate以扫描不同模块中的实体
EN

Stack Overflow用户
提问于 2015-10-23 23:13:35
回答 7查看 28.4K关注 0票数 20

我有模块A和模块B,它们都有JPA注解的类。模块B有一个单元测试,它从A中拉入几个这样的实体。两个模块都编译得很好,运行时依赖关系也设置得很好,但是当我尝试运行单元测试时,我得到了以下错误:

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

这发生在EntityManager.merge调用中。

由于模块B有所有的hibernate配置文件等,我猜它根本不能从A中提取我的类是一个实体。

我尝试将以下内容添加到persistence.xml中

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

在hibernate.cfg.xml中,我添加了:

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

然后:

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

这给了我一个错误,即"property“的内容必须匹配null。然后我试着:

<mapping class="myNamespace.*" />

我遗漏了什么?

我忘记提到的一件事可能很重要,那就是这两个模块被设置为单独的项目(我使用的是),所以目录结构是不同的。运行时依赖项都设置正确,但由于.class文件最终位于不同的目录中,我认为hibernate可能不会扫描这些文件。

EN

回答 7

Stack Overflow用户

发布于 2015-10-24 17:59:02

如果您将项目配置为自动检测实体,它将只扫描META-INF/persistence.xml所在的路径(默认情况下)。

除了:

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

您可以设置一个额外的休眠选项:

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

它确定Hibernate Entity Manager自动发现哪个元素。

对于额外的实体(在其他jar中),您可以在主persistence.xml文件中设置jar文件部分:

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

jar-file元素指定对包含托管持久性类的封装持久性单元可见的JAR文件,而class元素显式命名托管持久性类。

META-INF目录包含persistence.xml的JAR文件或目录称为持久性单元的根。持久性单元的作用域由持久性单元的根确定。每个持久性单元都必须使用对于持久性单元的作用域唯一的名称进行标识。

向您致敬,安德烈

票数 2
EN

Stack Overflow用户

发布于 2016-01-25 13:38:30

  • 如果您使用的是hibernate/spring,我们可以扩展LocalSessionFactoryBean对象并扫描整个项目以识别项目中的实体类。
  • 既然您说的是两个不同的项目,那么请尝试编写一些构建时实用程序来解析这两个项目,并创建一个实体xml文件来解决您的问题。
票数 2
EN

Stack Overflow用户

发布于 2018-02-23 01:31:47

做到这一点的简单方法

configuration.addAnnotatedClass(Contact.class)

如果你想使用scan by package,首先使用ClassLoader加载所有类。请参阅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);
        }
    }

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33305823

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档