Pergunta

Com hibernado você pode carregar seu Entity Aulas como:

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

Existe uma maneira de fazer a mesma coisa - carregando programaticamente suas classes de entidade - de uma maneira compatível com JPA 2.0?

A razão para esta pergunta é porque eu gostaria de dinamicamente carregar meu Entity classes, portanto, não necessariamente programaticamente.

Foi útil?

Solução

Com a ajuda da primavera, fiz isso de uma maneira compatível com JPA.

Minha "persistence.xml" parece vazia, sem entidades listadas dentro do <persistence-unit> elemento.

Escrevi então uma aula que implementou a persistenceUnitPostProcessor como assim:

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

Então eu ajustei meu contexto de primavera xml assim:

<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>

Observe o registro do ReflectionsPersistenceUnitPostProcessor na configuração de persistência.

E é isso. Toda aula com uma entidade JPA ou MappedSuperclass A anotação no caminho de classe é adicionada ao caminho de classe. Eu tive que dar reflexões o prefixo de um nome de pacote para escanear pelo qual é por isso que com.austinmichael está lá. Você pode registrar um segundo ReflectionsPersistenceUnitPostProcessor com um prefixo de nome de pacote diferente, se você quiser se suas entidades não compartilharem um prefixo de nome de pacote comum.

Mas, agora é o JPavendor Agnóstico.

Outras dicas

Existe uma maneira de fazer a mesma coisa - carregando programaticamente suas classes de entidade - de uma maneira compatível com JPA 2.0?

Não, isso não é suportado pelo JPA, então você terá que fazer isso de maneira específica do provedor. James Sutherland descreveu o processo para eclipselink em este tópico assim:

Você pode acessar o eclipselink ServerSession de EntityManagerFactoryImpl (getServerSession()) e use seu ' addDescriptor(ClassDescriptor) ou addDescriptors() API para adicionar eclipselink ClassDescriptor. Você precisará construir o ClassDescriptor Objetos de meta-dados diretamente você mesmo (ou use a bancada de trabalho de mapeamento para criá-los), pois o carregamento de anotações JPA ou ORM.XML seria mais difícil.

Também dê uma olhada nisso Tópico mais recente Para mais amostra de código (a API parece um pouco detalhada).

Referências

Eu não acho que exista essa opção - o JPA suporta a digitalização do caminho de classe em busca de entidades ou listando explicitamente as classes de entidade na persistência.xml. Como você está usando o Hibernate como provedor de persistência, mas sempre pode recorrer ao código de hiberna. Dê uma olhada no HibernateEntityManager e HibernateEntityManagerFactory Aulas. Você pode lançar fábricas e gerentes de entidades para o gerente de entidades e fazer as coisas habituais de hibernação.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top