小编典典

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

java

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

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

有没有一种方法可以以符合JPA 2.0的方式以编程方式加载Entity类来做同样的事情?

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


阅读 209

收藏
2020-09-18

共1个答案

小编典典

在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;
    }
}

然后我像这样调整了我的spring context 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>

注意ReflectionsPersistenceUnitPostProcessor在persistenceUnitPostProcessors设置中的注册。

就是这样。每个MappedSuperclass在类路径上具有JPA实体或注释的类都将添加到类路径中。我必须给反射一个要扫描的包名称的前缀,这就是为什么要使用它的原因com.austinmichaelReflectionsPersistenceUnitPostProcessor如果您的实体不共享通用的包名前缀,则可以使用其他包名前缀注册一秒钟。

但是,这是JPAVendor不可知的。

2020-09-18