我目前正在使用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;
}
}