복붙노트

[SPRING] Spring AOP로 Hibernate 세션 구성하기

SPRING

Spring AOP로 Hibernate 세션 구성하기

JPA 프로 바이더로서 Hibernate 4.3.8을 사용하는 Spring Framework 4 애플리케이션이 있습니다. 저는 Hibernate 필터를 사용하고 싶습니다. 따라서 그것을 가능하게 할 필요가 있습니다. 나는 Spring AOP로하려고하는이 애플리케이션에서 전 세계적으로 이것을하고 싶다. 아이디어는이 질문과이 질문에서와 같이 세션을 만들거나 가져올 때마다 필터를 사용할 수있게하는 측면을 쓸 수 있다는 것입니다.

내 프로젝트에 Maven을 사용하여 spring-aop과 aspectjweaver 의존성을 추가했다. 나는 다음과 같은면을 추가했다.

@Aspect
@Component
public class EnableHibernateFilters {
    @Pointcut("execution(* org.hibernate.SessionFactory.getCurrentSession(..))")
    protected void sessionBeingFetched() {

    }

    @AfterReturning(pointcut = "sessionBeingFetched()", returning = "object")
    public void enableFilters(JoinPoint joinPoint, Object object) {
        System.out.println("!!! Enabling filters !!!"); // Never printed

        Session session = (Session) object;
        session.enableFilter("myFilter");
    }
}

내 문제는 위의 조언 (enableFilters) 호출 된 적이있다; 텍스트가 인쇄되지 않고 내 필터가 사용 가능하지 않습니다. 내 aspect가 감지되었고 AOP가 내 프로젝트에서 pointcut을 내 자신의 클래스 중 하나로 변경함으로써 작동한다는 것을 확인했다. 또한 pointcut을 실행 (* org.hibernate.SessionFactory.openSession (..))으로 변경하려고 시도했지만 결과가 없습니다.

나는 SessionFactory를 명시 적으로 구성하지 않았기 때문에 이것이 Hibernate를 설정하는 방법으로 인해 발생한다고 생각한다. 오히려 EntityManagerFactory를 설정했습니다. 여기 내 구성입니다.

@Configuration
@EnableTransactionManagement
public class PersistenceConfig {
    @Bean
    public DataSource dataSource() throws NamingException {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/postgres"); // JNDI lookup
    }

    @Bean
    public EntityManagerFactory entityManagerFactory() throws SQLException, NamingException {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(false);
        vendorAdapter.setDatabase(Database.POSTGRESQL);
        vendorAdapter.setShowSql(true);
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setPackagesToScan(...);
        factory.setDataSource(this.dataSource());
        factory.afterPropertiesSet();

        return factory.getObject();
    }

    @Bean
    public JpaTransactionManager transactionManager() throws SQLException, NamingException {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(this.entityManagerFactory());

        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }
}

기본적으로 위의 구성에 어떤 pointcut을 사용할 지 모르겠습니다. LocalContainerEntityManagerFactoryBean.setLoadTimeWeaver ()를 사용하여 주위를 어지럽 혔습니다.하지만 알아낼 수는 없었습니다. 나는 어쨌든 그것을 구성 할 필요가 있는지조차 모른다.

기본적으로, 내 AOP 설치 내 자신의 사용자 지정 클래스에 대해 작동합니다. 문제는 위빙이 Hibernate 또는 무언가 (나는이 부분에 익숙하지 않다)로 구성되지 않았거나 세션이 내 설정으로 인해 SessionFactory.getCurrentSession () 메소드를 통해 얻어지지 않는다는 것입니다. 필자는 내 포인트 컷을 실행 (* org.hibernate.Hibernate.isInitialized (..))으로 변경하고 Hibernate.isInitialized (null)을 수동으로 호출함으로써 내 조언이 심지어 Hibernate와 함께 작동했는지 확인하려고 시도했다. 조언도 마찬가지이므로 문제가 될 수 있습니다. 나는이 게시물에서 Hibernate의 직조를 가능하게하기 위해 제안 된 것을 시도했지만, 어떤 변화도 가져 오지 못했습니다.

또한 pointcut을 실행 (* org.springframework.orm.hibernate4.SessionHolder.getSession (..)) 및 실행 (* org.springframework.orm.jpa.vendor.HibernateJpaDialect.getSession (..))으로 설정하려고 시도했지만, 행운도없이.

그래서 나는 다음에 어디로 가야할지 모르겠습니다. Hibernate의 Session 객체를 Hibernate 필터를 활성화 할 수 있도록 내 충고에서 어떻게 얻을 수 있습니까? 미리 감사드립니다.

편집하다: 경우에 따라 @EnableAspectJAutoProxy를 내 구성에 포함 시켰습니다.

@Configuration
@ComponentScan(basePackages = { ... })
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
    // ...
}

해결법

  1. ==============================

    1.어쩌면 org.hibernate.SessionFactory 인터페이스를 실행 인수로 사용하여 pointcut을 선언하고 있다는 사실 일 수도 있습니다 ...

    어쩌면 org.hibernate.SessionFactory 인터페이스를 실행 인수로 사용하여 pointcut을 선언하고 있다는 사실 일 수도 있습니다 ...

    @Pointcut ( "실행 (* org.hibernate.SessionFactory.getCurrentSession (..))")

    올바른 방법은 해당 인터페이스의 구현으로 pointcut의 실행을 정의하는 것이며 그 표기법은 약간 다릅니다. + 기호

    @Pointcut ( "실행 (* org.hibernate.SessionFactory + .getCurrentSession (..))")

    또한 대체 표기법 ...

    @Pointcut ( "within (org.hibernate.SessionFactory +) && execution (* getCurrentSession (..))")

    또한 aspectj-cheat-sheet를 봐야합니다.

    java.lang.IllegalArgumentException : final 클래스를 서브 클래스화할 수 없습니다. 목표로하는 클래스는 org.hibernate.SessionFactory의 구체적 구현물, 즉 org.hibernate.internal.SessionFactoryImpl인데,이 클래스는 최종 최종 public final 클래스 인 SessionFactoryImpl입니다.

    proxyTargetClass = 설명서에 따른 true 구성

    그러나 하위 클래스로 만들려고하는 클래스가 마지막이기 때문에 Java 언어 사양에 따라 약간의 문제가 있습니다.

  2. ==============================

    2.당신의 애스펙트 클래스는 좋아 보인다.

    당신의 애스펙트 클래스는 좋아 보인다.

    엔티티에 @Filter와 @FilterDef를 ​​추가하십시오.

    예 :

    @Entity
    @Table(name="myTable", schema="mySchema")
    @FilterDef(name="myFilter", parameters=@ParamDef(name="myAttribute", type="integer"))
    @Filter(name="myFilter", condition=":myAttribute <= attribute")
    public class MyEntity implements Serializable {
        ...
        @Column(name="attribute")
        private Integer attribute;
        ...
    }
    

    구성에서 필터는 사용 가능하지만 매개 변수는 없습니다.

    테스트 할 예제 :

    session.enableFilter("myFilter").setParameter("myAttribute", Integer.valueOf(2));
    

    물론 @FilterDef 주석에 필요한만큼의 매개 변수를 설정할 수 있습니다.

    그것을 원하면 당신을 도울 것입니다. 안드레.

  3. ==============================

    3.정확한 문제에 직면했다. EntityManager를 사용하고 sessionFactory의 getCurrentSession 호출을 중심으로 pointcut을 사용하여 세션 정보를 가져 오는 대신 unwrap 메소드를 사용하여 세션 정보를 가져와이를 해결할 수있었습니다.

    정확한 문제에 직면했다. EntityManager를 사용하고 sessionFactory의 getCurrentSession 호출을 중심으로 pointcut을 사용하여 세션 정보를 가져 오는 대신 unwrap 메소드를 사용하여 세션 정보를 가져와이를 해결할 수있었습니다.

    @PersistenceContext
    private EntityManager entityManager;
    
    @Around("myPointcut")
    public Object enableGlobalFilter(ProceedingJoinPoint pjp) throws Throwable {
                Session session = entityManager.unwrap(Session.class);
                Filter filter = session.enableFilter("Published_Entity");
                filter.setParameter("is_publishedParam", true);
                Object obj  = pjp.proceed();
                session.disableFilter("Published_Entity");
                return obj;
     }
    

    희망이 도움이됩니다.

  4. from https://stackoverflow.com/questions/32934397/configuring-hibernate-session-with-spring-aop by cc-by-sa and MIT license