以编程方式加载具有 JPA 2.0 的实体类?

2022-09-01 20:44:59

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

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

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

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


答案 1

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

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

然后我写了一个类,实现了 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;
    }
}

然后我调整了我的春季上下文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>

请注意持久性UnitPostProcessors设置中的注册。ReflectionsPersistenceUnitPostProcessor

就是这样。在类路径上具有 JPA 实体或注释的每个类都会添加到类路径中。我必须给反射一个软件包名称的前缀来扫描,这就是为什么根本就存在。如果需要,如果实体不共享公共包名称前缀,则可以使用其他包名称前缀注册第二个包名称前缀。MappedSuperclasscom.austinmichaelReflectionsPersistenceUnitPostProcessor

但是,这现在是JPAVendor不可知论者。


答案 2

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

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

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

另请查看此较新的线程以获取更多代码示例(API 看起来有点冗长)。

引用


推荐