24

使用 Hibernate,您可以将Entity类加载为:

sessionFactory = new AnnotationConfiguration()
                    .addPackage("test.animals")
                    .addAnnotatedClass(Flight.class)
                    .addAnnotatedClass(Sky.class)
                    .addAnnotatedClass(Person.class)
                    .addAnnotatedClass(Dog.class);

有没有办法以符合 JPA 2.0 的方式做同样的事情 - 以编程方式加载您的实体类?

这个问题的原因是因为我想动态加载我的Entity类,因此不一定以编程方式。

4

3 回答 3

28

在 Spring 的帮助下,我以符合 JPA 的方式做到了这一点。

<persistence-unit>我的“persistence.xml”看起来是空的,元素中没有列出任何实体。

然后我编写了一个实现 PersistenceUnitPostProcessor 的类,如下所示:

import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import org.reflections.Reflections;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;

public class ReflectionsPersistenceUnitPostProcessor implements PersistenceUnitPostProcessor {

    private String reflectionsRoot;
    private Logger log = LoggerFactory.getLogger(ReflectionsPersistenceUnitPostProcessor.class);

    @Override
    public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
            Reflections r = new Reflections(this.reflectionsRoot, new TypeAnnotationsScanner());
            Set<String> entityClasses = r.getStore().getTypesAnnotatedWith(Entity.class.getName());
            Set<String> mappedSuperClasses = r.getStore().getTypesAnnotatedWith(MappedSuperclass.class.getName());

            for (String clzz : mappedSuperClasses)
            {
                    pui.addManagedClassName(clzz);
            }


            for (String clzz : entityClasses)
            {
                    pui.addManagedClassName(clzz);
            }

    }

    public String getReflectionsRoot() {
            return reflectionsRoot;
    }

    public void setReflectionsRoot(String reflectionsRoot) {
            this.reflectionsRoot = reflectionsRoot;
    }
}

然后我像这样调整了我的spring上下文xml:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="jpaVendorAdapter">
                    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                            <property name="showSql" value="false" />
                            <property name="generateDdl" value="true" />
                            <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
                    </bean>
            </property>
            <property name="persistenceUnitName" value="GenericPersistenceUnit"/>
            <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
            <property name="persistenceUnitPostProcessors">
                    <list>
                            <bean class="com.austinmichael.core.repository.ReflectionsPersistenceUnitPostProcessor">
                                    <property name="reflectionsRoot" value="com.austinmichael"/>
                            </bean>
                    </list>
            </property>
    </bean>

注意ReflectionsPersistenceUnitPostProcessorpersistenceUnitPostProcessors 设置中的注册。

就是这样。在类路径上具有 JPA 实体或MappedSuperclass注释的每个类都将添加到类路径中。我必须给反射一个包名称的前缀来扫描,这就是为什么com.austinmichael存在。ReflectionsPersistenceUnitPostProcessor如果您的实体不共享通用的包名称前缀,您可以根据需要使用不同的包名称前缀注册第二个。

但是,这现在与 JPAVendor 无关。

于 2011-12-27T20:04:00.153 回答
5

有没有办法以符合 JPA 2.0 的方式做同样的事情 - 以编程方式加载您的实体类?

不,这不受 JPA 支持,因此您必须以提供者特定的方式执行此操作。James Sutherland 在这个线程中描述了 EclipseLink 的过程,如下所示:

您可以ServerSessionEntityManagerFactoryImpl( getServerSession()) 访问 EclipseLink,并使用其addDescriptor(ClassDescriptor)addDescriptors()API 添加 EclipseLink ClassDescriptor。您需要ClassDescriptor自己直接构建元数据对象(或使用 Mapping Workbench 创建它们),因为从 JPA 注释或 orm.xml 加载会更加困难。

还可以查看这个更新的线程以获取更多代码示例(API 看起来有点冗长)。

参考

于 2010-05-23T17:11:11.480 回答
3

我不认为有这样的选项 - JPA 支持扫描实体的类路径或在 persistence.xml 中明确列出实体类。由于您使用休眠作为持久性提供程序,但是您始终可以使用休眠代码。看看HibernateEntityManagerHibernateEntityManagerFactory类。您可以将实体管理器工厂和实体管理器转换为它们并执行通常的休眠操作。

于 2010-05-15T04:51:55.350 回答