2013-10-07 6 views
6

私は、データアクセスレイヤーでJPA-2.0をHibernateとともに使用しています。監査ログの目的のためにJPAのエンティティマネージャをHibernateのEmptyInterceptorに挿入

は、私がpersistence.xmlでプロパティの下に設定することで、HibernateのEmptyInterceptorを使用しています:AuditLogInterceptorが休止状態の 'org.hibernate.EmptyInterceptor' 拡張

<property name="hibernate.ejb.interceptor" 
       value="com.mycom.audit.AuditLogInterceptor" /> 

public class AuditLogInterceptor extends EmptyInterceptor { 

    private Long userId; 

    public AuditLogInterceptor() {} 

    @Override 
    public boolean onSave(Object entity, Serializable id, Object[] state, 
      String[] propertyNames, Type[] types) throws CallbackException { 
     // Need to perform database operations using JPA entity manager 
     return false; 
    } 

    @Override 
    public boolean onFlushDirty(Object entity, Serializable id, 
      Object[] currentState, Object[] previousState, 
      String[] propertyNames, Type[] types) { 
     // other code here   
     return false; 
    } 

    @Override 
    public void postFlush(Iterator iterator) throws CallbackException { 
     System.out.println("I am on postFlush"); 
     // other code here 
    } 
} 

私はデータベースアクセスを実行するためにデータアクセス層でJPAエンティティマネージャを使用しています。 JPAの構成は以下のようなものです:

<bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
     p:persistenceUnitName="PersistenceUnit" 
     p:persistenceXmlLocation="classpath*:persistence.xml" 
     p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter"> 
     <property name="loadTimeWeaver"> 
      <bean 
       class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> 
     </property> 
    </bean> 

マイAbstractDAOは次のとおりです。

public class AbstractDao<T, ID extends Serializable> { 

    private final transient Class<T> persistentClass; 

    protected transient EntityManager entityManager; 

    @SuppressWarnings("unchecked") 
    public AbstractDao() { 

     this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
    } 

    @PersistenceContext 
    public final void setEntityManager(final EntityManager entityMgrToSet) { 

     this.entityManager = entityMgrToSet; 
    } 

    public final Class<T> getPersistentClass() { 

     return persistentClass; 
    } 

    public final void persist(final T entity) { 

     entityManager.persist(entity);  
    } 

} 

私は私のような「AuditLogInterceptor」にデータベース操作を実行できるように、「AuditLogInterceptor」内のJPAエンティティマネージャを注入したいと思います抽象的なDAO。

適切な解決策は何でしょうか?

答えて

7

私はアプリケーションコンテキストの参照を与える私はクラスの下に作成した「AuditLogInterceptor」

にJPAエンティティマネージャを使用してデータベース操作を実行するための簡単な方法を持っています:

@Repository("myAuditDAO") 
public class myAuditDAO<T, ID extends Serializable> { 

    private final transient Class<T> persistentClass; 

    protected transient EntityManager entityManager; 

    @SuppressWarnings("unchecked") 
    public MyDAO() { 

     this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
    } 

    @PersistenceContext 
    public final void setEntityManager(final EntityManager entityMgrToSet) { 

     this.entityManager = entityMgrToSet; 
    } 

    public final Class<T> getPersistentClass() { 

     return persistentClass; 
    } 

    public final T findById(final ID theId) { 

     return entityManager.find(persistentClass, theId); 
    } 

    public final void persist(final T entity) { 

     entityManager.persist(entity); 
    } 

    public final void merge(final T entity) { 

     entityManager.merge(entity); 
    } 
} 

とJPA entiを持っている 'MyAuditDAO' の参照を取得するために 'AuditLogInterceptor' で 'ApplicationContextProvider' を使用DAOの初期化中に注入されるプロパティとして管理者に通知します。 「MyAuditDAO」の助けを借りて、私はデータベース操作を実行できます。

public class AuditLogInterceptor extends EmptyInterceptor { 

    @Override 
    public void postFlush(Iterator iterator) throws CallbackException { 

     // Here we can get the MyAuditDao reference and can perform persiste/merge options 
     MyAuditDao myAuditDao = (MyAuditDao) ApplicationContextProvider.getApplicationContext().getBean("myAuditDao"); 

     // myAuditDao.persist(myEntity); 

    } 
} 
+0

スレッドの安全性はどうですか? –

+0

私はJPA2でauditLogRepositoryへの参照を取得しようとしていますが、@ Resourceアノテーションを使用して何も注入せずにNPEを残してしまったためです。 – Stephane

0

抽象クラスでpersistenceManagerが正常に開始されたと考えています。 AbstractDaoを拡張するクラスAuditLogDAOがあります。 AuditLogDAOクラスをインターセプタに注入し、auditLogDAO.save(entity);などのメソッドを呼び出します。

DB操作を実行し、utilクラスをインターセプタに注入するUtilクラスを作成してください。

@Component("applicationContextProvider") 
    public class ApplicationContextProvider implements ApplicationContextAware { 
     private static ApplicationContext context; 

     public static ApplicationContext getApplicationContext() { 
      return context; 
     } 

     @Override 
     public void setApplicationContext(ApplicationContext ctx) { 
      context = ctx; 
     } 
    } 

作成されたデータアクセスクラス:

関連する問題