简体   繁体   中英

Hibernate JPA interceptor doesn't get call

The setup I have an old project that is stuck to jdk 1.5, thus spring and hibernate versions are also the maximum possible to support this version of java. Hibernate is 3.3.2.GA and spring is 3.1.1.RELEASE. Setup is the following:

<persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL">
    <mapping-file>persistence-query.xml</mapping-file>
    ...
    <properties>
        <property name="hibernate.max_fetch_depth" value="3" />
        <property name="hibernate.show_sql" value="true" />
        <property name="hibernate.format_sql" value="true" />
        <property name="hibernate.hbm2ddl.auto" value="validate" />
        <property name="hibernate.ejb.interceptor" value="com.myproj.common.dao.AuditInterceptor"/>         
    </properties>
</persistence-unit>

application context:

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jee="http://www.springframework.org/schema/jee"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="..."/>                                         
<tx:annotation-driven transaction-manager="transactionManager" />   
<aop:aspectj-autoproxy/>   
<bean id="applicationContextProvder" class="com.myproj.common.utils.ApplicationContextProvider"/>   
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
 <property name="dataSource" ref="dataSource" />
</bean>

 <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath:persistence.xml" />
    <property name="persistenceUnitName" value="myUnit" />
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
    <property name="jpaDialect" ref="jpaDialect" />
 </bean>

<bean id="jpaVendorAdapter"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="database" value="ORACLE" />
    <property name="showSql" value="true" />
</bean>

<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />

<!-- Local transaction management -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <property name="dataSource" ref="dataSource" />
    <property name="jpaDialect" ref="jpaDialect" />
</bean> 

and my interceptor:

@Component
public class AuditInterceptor extends EmptyInterceptor {

private static final long serialVersionUID = 98658932451L;

@Autowired
private JdbcTemplate jdbcTemplate;

public void afterTransactionBegin(Transaction tx) {
    if (user != null) {
        jdbcTemplate.execute("call ah_audit_pkg.SetAudit('test')");
        super.afterTransactionBegin(tx);
     }
 }  
}

I run a junit to test that interceptor is getting called and it is not. In debug mode, I am able to see this: 在此处输入图片说明

Any help is appreciated! Why my intercetprot is not getting called.

Edit:

I also tried the interceptor to override the afterTransactionBegin but it didn't help.

I ended up with the following solution: I have my entityt that extends from a superclass mapped entity:

@Entity
@Table(name = "my_table")
public class MyTable extends AuditInfo

The AuditInfo entity has the following mapping:

@MappedSuperclass
public abstract class AuditInfo implements Serializable {

...

    @PrePersist
    void onCreate() throws SQLException {
        //this empty method is needed for AOP to trigger the audit information insert before entity is stored
    }

    @PreUpdate
    void onPersist() throws SQLException {
        //this empty method is needed for AOP to trigger the audit information insert before entity is updated
    }

    @PreRemove
    void onRemove() throws SQLException {
        //this empty method is needed for AOP to trigger the audit information insert before entity is removed
    }
}

And the Aspect class:

@Aspect
@Component
public class MyAspect {

    @Before("execution(* com.mypackage.entities.AuditInfo.on*(..))")
    public void setAuditHistory(JoinPoint jp){      
        final AuditInfo info = ((AuditInfo)jp.getThis());
        JdbcTemplate jdbcTemplate = ApplicationContextProvider.getApplicationContext().getBean(JdbcTemplate.class);
        jdbcTemplate.execute(new CallableStatementCreator() {
            public CallableStatement createCallableStatement(Connection conn) throws SQLException {
                CallableStatement stmt = conn.prepareCall("begin ah_audit_pkg.SetAudit(?,?); end;");
                stmt.setString(1, info.getAuditUser());
                if(info.getAuditLocation() != null && info.getAuditLocation().trim().length() !=0) {
                    stmt.setString(2, info.getAuditLocation());
                } else {
                    stmt.setString(2, info.getAuditUser());
                }
                return stmt;
            }
        }, new CallableStatementCallback<Object>() {
            public Object doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
                return cs.executeUpdate();
            }
        });
    }  
}

It is to be noted that the Spring beans are extracted from the context and not autowired - this is because AOP is a singleton class in spring implementation, and none of the autowired beans will be ever instantiated even if they are available in the context. So I had to manually retrieve them for later usage.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM