以编程方式使用JPA 2.0加载实体类?

wen*_*wen 22 java entities dynamic jpa-2.0

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

sessionFactory = new AnnotationConfiguration()
                    .addPackage("test.animals")
                    .addAnnotatedClass(Flight.class)
                    .addAnnotatedClass(Sky.class)
                    .addAnnotatedClass(Person.class)
                    .addAnnotatedClass(Dog.class);
Run Code Online (Sandbox Code Playgroud)

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

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

小智 27

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

我的"persistence.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我像这样调整了我的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>
Run Code Online (Sandbox Code Playgroud)

请注意ReflectionsPersistenceUnitPostProcessorpersistenceUnitPostProcessors设置中的注册.

就是这样.MappedSuperclass在类路径中将每个具有JPA实体或注释的类添加到类路径中.我必须给出思考包名称的前缀以便扫描,这就是为什么com.austinmichael存在的原因.ReflectionsPersistenceUnitPostProcessor如果您的实体不共享公共包名称前缀,您可以使用不同的包名称前缀注册第二个.

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


Pas*_*ent 5

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

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

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

还要看一下这个更新的线程以获取更多代码示例(API看起来有点冗长).

参考