Таблица аудита с использованием "Envers" в Spring Hibernate java project
Нам нужно провести аудит существующей таблицы с помощью envers. у нас нет hibernate.xml, а мы используем application-context.xml. И мы создаем схему через "Liquibase-changeet", затем как я могу создавать аннотации, такие как @Entity и @Audited.
Как решить эту проблему?
Я добавил настройки конфигурации спящего режима
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="hibernate.ejb.event.post-insert">org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.post-update">org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.post-delete">org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.pre-collection-update">org.hibernate.envers.event.AuditEventListener</prop>
<!-- <prop key="hibernate.ejb.event.pre-collection-remove">org.hibernate.envers.event.AuditEventListener</prop>
<prop key="hibernate.ejb.event.post-collection-recreate">org.hibernate.envers.event.AuditEventListener</prop> -->
<prop key="org.hibernate.envers.revision_field_name">REV</prop>
<prop key="org.hibernate.envers.revision_type_field_name">REVTYPE</prop>
<prop key="org.hibernate.envers.auditTablePrefix"></prop>
<prop key="org.hibernate.envers.auditTableSuffix">_HISTORY</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
Добавлена @Аудированная аннотация в моем классе домена
@Entity
@Audited
@Table(name="user")
public class User implements Serializable {
Но эта конфигурация удалила мои существующие таблицы
например
Mydatabase
-----------
user
product
order_details
user_role
login
У меня есть 5 таблиц в моей базе данных. После запуска моего приложения он отображает 3 таблицы. Вместо создания таблицы "аудита" она удаляет существующую таблицу.
Mydatabase
-----------
user
product
order_details
Как создать таблицу аудита (_HISTORY), не касаясь существующих таблиц???
Ответы
Ответ 1
В наборе изменений Liquibase определите определение таблицы аудита, как и для любой другой таблицы.
Пропустите свойство hibernate.hbm2ddl.auto
в spring -hibernate ocnfiguration.That будет инструктировать спящий режим ничего не делать с этой схемой.
Сохраняя остальную часть вашей конфигурации, она должна работать.
Просто убедитесь, что имена таблиц аудита в схеме и в соответствии с конфигурацией.
Ссылка на документ, подробно описывающий, как его сделать, если схема сгенерирована с помощью ant
Ответ 2
Я столкнулся с той же проблемой, чтобы ее решить, я выполнил следующие шаги:
в
<prop key="hibernate.hbm2ddl.auto">update</prop>
-
Если вы работаете с ENVERS Hibernet-envers 3.5.5 или +, вы должны иметь эту конфигурацию в контексте приложения:
<property name="eventListeners">
<map>
<entry key="post-insert" >
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="post-update">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="post-delete">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="pre-collection-update">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="pre-collection-remove">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
<entry key="post-collection-recreate">
<bean class="org.hibernate.envers.event.AuditEventListener" />
</entry>
</map>
</property>
-
Вы должны определить объект ревизии, такой как этот:
@Entity
@Table(name = "MY_REVINFO")
@RevisionEntity(MyRevisionListener.class)//@see next class
public class MyRevisionEntity {
private static final long serialVersionUID =1L;
@Id
@GeneratedValue
@RevisionNumber
private int id;
@RevisionTimestamp
private long timestamp;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Transient
public Date getRevisionDate() {
return new Date(timestamp);
}
@Column(name = "USER_NAME")
private String userName;
@Column(name = "DATE_OPER")
private Date dateOperation;
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DefaultRevisionEntity)) return false;
DefaultRevisionEntity that = (DefaultRevisionEntity) o;
if (id != that.getId()) return false;
if (timestamp != that.getTimestamp()) return false;
return true;
}
public int hashCode() {
int result;
result = id;
result = 31 * result + (int) (timestamp ^ (timestamp >>> 32));
return result;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getDateOperation() {
return dateOperation;
}
public void setDateOperation(Date dateOperation) {
this.dateOperation = dateOperation;
}
public String toString() {
return "DefaultRevisionEntity(id = " + id + ", revisionDate = " + DateFormat.getDateTimeInstance().format(getRevisionDate()) + ")";
}
}
-
Добавьте сопоставление этого нового объекта в свой application-context.xml как:
<value>mypackage.MyRevisionEntity</value>
-
Создайте слушателя (очень полезно, если вы хотите сохранить имя пользователя и время работы):
public class MyRevisionListener implements RevisionListener {
public void newRevision(Object revisionEntity) {
MyRevisionEntity revision = (MyRevisionEntity) revisionEntity;
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String userName="---";
if (userDetails != null) {
userName=userDetails.getUsername();
} else {
userName="UNKNOWN";
}
revision.setUserName(userName);
revision.setDateOperation(new Date(revision.getTimestamp()));
}
}
-
Очистите, установите и запустите приложение.
-
Если проблема не устранена, попробуйте обновить версию Envers (Hibrenate-envers и Hibernate-core)
Надеюсь на эту помощь.
Ответ 3
Попробуйте изменить стратегию DDL:
<prop key="hibernate.hbm2ddl.auto">create</prop>
в
<prop key="hibernate.hbm2ddl.auto">update</prop>
Стратегия генерации обновлений DDL не должна удалять существующую таблицу.
Ответ 4
Я работаю над проектом, использующим JPA с внедрением Hibernate, и нам удалось сделать работу без особых проблем, используя только конфигурацию на основе контекста x w760 > (мы не используем persistence.xml).
Наша конфигурация основана на поддержке JPA Spring JPA, но вы можете найти аналогичное решение:
<bean id="projectEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
<property name="packagesToScan">
<list>
<value>com.teimas.myproject.bo</value>
<value>com.teimas.myproject.bo.commons</value>
<value>com.teimas.myproject.bo.util</value>
</list>
</property>
<property name="persistenceUnitName" value="projectPU" />
<property name="jtaDataSource" ref="projectDataSourceTarget" />
<!-- Other ptops for hibernate config -->
<property name="jpaProperties" ref="jpaHibernateProperties" />
</bean>
<util:properties id="jpaHibernateProperties">
<prop key="hibernate.transaction.jta.platform">
org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform
</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<!-- validate | update | create | create-drop -->
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="javax.persistence.transactionType">JTA</prop>
<prop key="javax.persistence.validation.mode">AUTO</prop>
</util:properties>
Ключ состоит в том, что мы используем в качестве поставщика JPA объект спящего режима: org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter и добавляем свойство packagesToScan, чтобы сообщить hibernate для сканирования аннотаций в этих пакетах. Таким образом, Hibernate находит Envers и Validation anotations, и все работает нормально.
Надеюсь, что это поможет.