审计跟踪期间的未知实体。 (Hibernate 5,Spring4)

时间:2017-02-20 09:54:22

标签: java spring hibernate audit-trail

我目前正在使用Interceptor为我的Web应用程序执行审计跟踪。

但是,当我尝试将详细信息保存到DB时,我遇到了以下问题:

org.hibernate.MappingException: Unknown entity: com.demo.domain.AuditLog

我认为我的applicationContext中存在映射问题,因为我的其他类工作正常。

我是否以正确的方式进行审计跟踪?

MyInterceptor类:

package com.demo.common;

import java.io.Serializable;
import java.util.Date;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.EmptyInterceptor;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.type.Type;

import com.demo.domain.AuditLog;
import com.demo.domain.LoginLog;
import com.demo.util.GlobUtil;

public class MyInterceptor extends EmptyInterceptor
{
    private static final Logger log = LogManager.getLogger(MyInterceptor.class);

    public static final String OPERATION_TYPE_INSERT = "INSERT";

    public static final String OPERATION_TYPE_UPDATE = "UPDATE";

    public static final String OPERATION_TYPE_DELETE = "DELETE";

    // delete
    public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
    {
        Session session = HibernateUtil.getSessionFactory().openSession();

        try
        {
            // TODO Auto-generated method stub
            for (int index = 0; index < propertyNames.length; index++)
            {
                String prev = (state[index] == null) ? "" : state[index].toString();

                AuditLog auditLog = new AuditLog(id.toString(), entity.getClass().toString(),
                        propertyNames[index].toString(), prev, "", OPERATION_TYPE_DELETE, GlobUtil.getUserName(),
                        new Date());
                System.out.println(auditLog.toString());

                session.beginTransaction();

                try
                {
                    session.save(auditLog);
                    session.getTransaction().commit();
                }
                catch (HibernateException e)
                {
                    session.getTransaction().rollback();
                    throw e;
                }
            }
        }
        catch (HibernateException e)
        {
            log.error("Unable to process audit log for DELETE operation", e);
        }
        finally
        {
            session.close();
        }
    }

    // update
    public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
            String[] propertyNames, Type[] types)
    {

        Session session = HibernateUtil.getSessionFactory().openSession();

        try
        {
            for (int index = 0; index < propertyNames.length; index++)
            {
                String prev = (previousState[index] == null) ? "" : previousState[index].toString();
                String curr = (currentState[index] == null) ? "" : currentState[index].toString();

                AuditLog auditLog = new AuditLog(id.toString(), entity.getClass().toString(),
                        propertyNames[index].toString(), prev, curr, OPERATION_TYPE_UPDATE, GlobUtil.getUserName(),
                        new Date());
                System.out.println(auditLog.toString());

                session.beginTransaction();

                try
                {
                    session.save(auditLog);
                    session.getTransaction().commit();
                }
                catch (HibernateException e)
                {
                    session.getTransaction().rollback();
                    throw e;
                }
            }
        }
        catch (HibernateException e)
        {
            log.error("Unable to process audit log for DELETE operation", e);
        }
        finally
        {
            session.close();
        }

        return true;
    }

    public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
    {
        // do nothing
        return true;
    }

    // insert
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
    {
        Session session = HibernateUtil.getSessionFactory().openSession();

        if (!autitable(entity))
        {
            return false;
        }

        try
        {
            for (int index = 0; index < propertyNames.length; index++)
            {
                String curr = (state[index] == null) ? "" : state[index].toString();

                AuditLog auditLog = new AuditLog(id.toString(), entity.getClass().toString(),
                        propertyNames[index].toString(), "", curr, OPERATION_TYPE_INSERT, GlobUtil.getUserName(),
                        new Date());
                System.out.println(auditLog.toString());

                session.beginTransaction();

                try
                {
                    session.save(auditLog);
                    session.getTransaction().commit();
                }
                catch (HibernateException e)
                {
                    session.getTransaction().rollback();
                    throw e;
                }
            }
        }
        catch (HibernateException e)
        {
            log.error("Unable to process audit log for DELETE operation", e);
        }
        finally
        {
            session.close();
        }

        return true;
    }

    private boolean autitable(Object entity)
    {
        if (entity instanceof LoginLog || entity instanceof AuditLog)
        {
            return false;
        }

        return true;
    }
}

的applicationContext-hibernate.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    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.xsd
    http://www.springframework.org/schema/jdbc 
    http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd 
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">

<tx:annotation-driven />

<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean 
    below) -->
<tx:advice id="txAdvice">
    <!-- the transactional semantics... -->
    <tx:attributes>
        <tx:method name="*_TransNew" propagation="REQUIRES_NEW" />
        <tx:method name="*_NoTrans" propagation="NEVER" />

        <tx:method name="create*" propagation="REQUIRED" />
        <tx:method name="update*" propagation="REQUIRED" />
        <tx:method name="delete*" propagation="REQUIRED" />
        <tx:method name="add*" propagation="REQUIRED" />

        <tx:method name="generate*" propagation="REQUIRED" />
        <tx:method name="get*" propagation="REQUIRED" />
        <tx:method name="is*" propagation="REQUIRED" />

        <!-- other methods use the default transaction settings (see below) -->
        <tx:method name="*" read-only="true" />
    </tx:attributes>
</tx:advice>

<!-- ensure that the above transactional advice runs for any execution of 
    an operation defined by the following -->
<aop:config>
    <aop:pointcut id="demoServiceOperations"
        expression="execution(* com.demo.*.service.*.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="demoServiceOperations" />
</aop:config>

<!-- Use datasource setup in server (wildfly) -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName">
        <value>java:/DemoDS</value>
    </property>
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2012Dialect</prop>
            <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
            </prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
            <prop key="hibernate.jdbc.batch_size">50</prop>
            <prop key="hibernate.order_inserts">true</prop>
            <prop key="hibernate.order_updates">true</prop>

            <prop key="hibernate.c3p0.min_size">5</prop>
            <prop key="hibernate.c3p0.max_size">20</prop>
            <prop key="hibernate.c3p0.timeout">1800</prop>
            <prop key="hibernate.c3p0.max_statements">1000</prop>
            <prop key="hibernate.c3p0.numHelperThreads">5</prop>
        </props>
    </property>

    <property name="entityInterceptor">
             <bean class="com.demo.common.MyInterceptor"/>
    </property> 

    <!-- Scan whole folder -->
    <property name="mappingLocations" value="classpath:com/demo/domain/*.hbm.xml" />
</bean>

<bean
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"
    id="PersistenceExceptionTranslator" />

<bean id="transactionManager"
    class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- DAO Beans here -->

</beans>

控制台:

    2017-02-20 17:38:13,760 ERROR - Unable to process audit log for DELETE operation
org.hibernate.MappingException: Unknown entity: com.demo.domain.AuditLog
    at org.hibernate.metamodel.internal.MetamodelImpl.entityPersister(MetamodelImpl.java:620)
    at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1627)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:104)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:682)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:674)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:669)
    at com.demo.common.MyInterceptor.onSave(MyInterceptor.java:148)

AuditLog.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.demo.domain.AuditLog" table="TBLMDM_AUDIT_LOG" optimistic-lock="version" dynamic-update="true">
        <id name="auditId" type="java.lang.Integer">
            <column name="AUDIT_ID" />
            <generator class="identity" />
        </id>
        <property name="entityId" type="string">
            <column name="ENTITY_ID" not-null="true" />
        </property>
        <property name="tableName" type="string">
            <column name="TABLE_NAME" length="50" />
        </property>
        <property name="property" type="string">
            <column name="PROPERTY" />
        </property>
        <property name="oldValue" type="string">
            <column name="OLD_VALUE" />
        </property>
        <property name="newValue" type="string">
            <column name="NEW_VALUE" />
        </property>
        <property name="action" type="string">
            <column name="ACTION" length="50" />
        </property>
        <property name="actionBy" type="string">
            <column name="ACTION_BY" length="50" />
        </property>
        <property name="createdDate" type="java.util.Date">
            <column name="CREATED_DATE" />
        </property>
    </class>
</hibernate-mapping>

*****编辑*****

我找到了问题的根源。

return new Configuration().configure().buildSessionFactory();

从类路径获取默认的hibernate.cfg.xml文件。但是如何在web-inf中获取applicationContext-Hibernate.xml?

我无法使用servletContext,因为它不在servlet中。

HibernateUtil类:

public class HibernateUtil
{

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory()
    {
        try
        {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        }
        catch (Throwable ex)
        {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory()
    {
        return sessionFactory;
    }
}

0 个答案:

没有答案