Pergunta

Nós usamos o Hibernate (com JPA e Hibernate Envers persistir história de objetos.O aplicativo da web seja executado muitos segmentos, alguns deles são criados por RMI invocação de método a partir de outros aplicativos, alguns deles são criados pela própria aplicação e alguns deles são criados para lidar com solicitações http (que geram pontos de vista).

Nós também usamos a Sessão Aberta Na Visualização padrão para gerenciar sessões, de modo que a nossa web.xml contém:

<filter>
    <filter-name>openEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>openEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Banco de dados é acessado usando DAOs, todos eles têm EntityManagers injetado pela Primavera.

@PersistenceContext
protected EntityManager em;

@PersistenceUnit
protected EntityManagerFactory emf;

Tudo funcionou muito bem, antes de nós decidiu usar o Hibernate Envers.Quando qualquer segmento que não é uma vista de geração de thread que executa o código para obter uma versão antiga de um objeto, a exceção é lançada.

@Override
public O loadByRevision(Long revision, Long id) {
    @SuppressWarnings("unchecked")
    O object = (O) AuditReaderFactory.get(em).createQuery().forEntitiesAtRevision(getBaseClass(), revision.intValue())
            .add(AuditEntity.id().eq(id)).getSingleResult();
    return object;
}

Exception in thread "Programador" org.o hibernate.SessionException:Sessão é fechada!no org.o hibernate.interno.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:129) no org.o hibernate.interno.SessionImpl.createQuery(SessionImpl.java:1776) no org.o hibernate.envers.as ferramentas.consulta.QueryBuilder.toQuery(QueryBuilder.java:226) no org.o hibernate.envers.consulta.impl.AbstractAuditQuery.buildQuery(AbstractAuditQuery.java:92) no org.o hibernate.envers.consulta.impl.EntitiesAtRevisionQuery.(lista de EntitiesAtRevisionQuery.java:108) no org.o hibernate.envers.consulta.impl.AbstractAuditQuery.getSingleResult(AbstractAuditQuery.java:110) (...)

Quando o código acima é executado pela vista de geração de thread funciona bem.Além disso, o não-envers código DAO funciona bem para cada thread.Por exemplo, o trecho abaixo

@Override
public O load(Long id) {
    final O find = em.find(getBaseClass(), id);
    return find;
}

pode ser executado através de RMI fios, sem problemas.

Por que não ver os tópicos chamada de métodos na entidade gestora, sem exceções, mas não pode usar Envers' AuditReaderFactory com a entidade manager?Eu pensei que talvez chamar um método em que a entidade manager cria uma sessão temporária, mas que não acontece quando usando o Envers, é verdade?

Qual é a melhor maneira de corrigir esse problema (para que o AuditReaderFactory pode ser usado de cada segmento)?

Foi útil?

Solução

Nós não descobrimos o porquê de, em não-segmentos de interface do usuário chamadas de método em EntityManagerFactory funcionou, mas chamadas de método em AuditReaderFactory não.De qualquer maneira, nós encontramos uma maneira de corrigi-lo.

A solução foi anotar métodos com @Transactional.Se qualquer método na cadeia de chamada antes da chamada para o AuditReaderFactory foi marcado como @Transactional, não houve SessionException não segmentos de interface do usuário.

Descobriu-se que fazer loadByRevision transacional não foi suficiente.Se um objeto retornado por esse método contido lenta carregado persistente de bolsas, o acesso a eles fora do loadByRevision escopo do método causados LazyInitializationException (não houve sessão).

A solução final foi para certificar-se de que, se qualquer segmento deseja carregar alguns dados do banco de dados, todo o carregamento (um objeto e acessar lenta carregado coleções) vai ser feito dentro de um método anotado com @Transactional.

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