Estoy agregando enversiones a entidades de hibernación existentes. Todo está funcionando sin problemas en cuanto a la auditoría, sin embargo, la consulta es un problema diferente porque las tablas de revisión no están pobladas con los datos existentes. ¿Alguien más ya ha resuelto este problema? ¿Tal vez has encontrado alguna manera de completar las tablas de revisión con la tabla existente? Solo pensé en preguntar, estoy seguro de que otros lo encontrarían útil.Rellenar las tablas de revisión de enversiones con los datos existentes de las entidades de Hibernate
Respuesta
No es necesario.
AuditQuery le permite obtener tanto RevisionEntity y revisión de datos por:
AuditQuery query = getAuditReader().createQuery()
.forRevisionsOfEntity(YourAuditedEntity.class, false, false);
Este será construir una consulta que devuelve una lista de objetos [3]. El elemento Fisrt es su información, el segundo es la entidad de revisión y el tercero es el tipo de revisión.
¿Podría ampliar esto más? ¿Estás diciendo que si la entidad de revisión es nula, entonces deberías simplemente usar el primer elemento de la matriz devuelta por AuditQuery? – Rezler
Tome un vistazo a http://www.jboss.org/files/envers/docs/index.html#revisionlog
Básicamente se puede definir su propio 'tipo de revisión' mediante anotación @RevisionEntity, y luego implementar una interfaz RevisionListener que introducir sus datos de auditoría adicionales, como usuario actual y el funcionamiento de alto nivel . Usualmente esos son extraídos del contexto de ThreadLocal.
Hemos rellenado los datos iniciales ejecutando una serie de consultas SQL sin formato para simular "insertar" todas las entidades existentes como si acabaran de crearse al mismo tiempo. Por ejemplo:
insert into REVINFO(REV,REVTSTMP) values (1,1322687394907);
-- this is the initial revision, with an arbitrary timestamp
insert into item_AUD(REV,REVTYPE,id,col1,col1) select 1,0,id,col1,col2 from item;
-- this copies the relevant row data from the entity table to the audit table
Nota que el valor RevType es para indicar un inserto (en oposición a una modificación).
Este enfoque me ha funcionado para resolver 'javax.persistence.EntityNotFoundException: no se ha podido encontrar
hemos resuelto el problema de poblar los registros de auditoría con los datos existentes de la siguiente manera:
SessionFactory defaultSessionFactory;
// special configured sessionfactory with envers audit listener + an interceptor
// which flags all properties as dirty, even if they are not.
SessionFactory replicationSessionFactory;
// Entities must be retrieved with a different session factory, otherwise the
// auditing tables are not updated. (this might be because I did something
// wrong, I don't know, but I know it works if you do it as described above. Feel
// free to improve)
FooDao fooDao = new FooDao();
fooDao.setSessionFactory(defaultSessionFactory);
List<Foo> all = fooDao.findAll();
// cleanup and close connection for fooDao here.
..
// Obtain a session from the replicationSessionFactory here eg.
Session session = replicationSessionFactory.getCurrentSession();
// replicate all data, overwrite data if en entry for that id already exists
// the trick is to let both session factories point to the SAME database.
// By updating the data in the existing db, the audit listener gets triggered,
// and inserts your "initial" data in the audit tables.
for(Foo foo: all) {
session.replicate(foo, ReplicationMode.OVERWRITE);
}
La configuración de mis fuentes de datos (a través de la primavera):
<bean id="replicationDataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value=".."/>
<property name="username" value=".."/>
<property name="password" value=".."/>
<aop:scoped-proxy proxy-target-class="true"/>
</bean>
<bean id="auditEventListener"
class="org.hibernate.envers.event.AuditEventListener"/>
<bean id="replicationSessionFactory"
class="o.s.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="entityInterceptor">
<bean class="com.foo.DirtyCheckByPassInterceptor"/>
</property>
<property name="dataSource" ref="replicationDataSource"/>
<property name="packagesToScan">
<list>
<value>com.foo.**</value>
</list>
</property>
<property name="hibernateProperties">
<props>
..
<prop key="org.hibernate.envers.audit_table_prefix">AUDIT_</prop>
<prop key="org.hibernate.envers.audit_table_suffix"></prop>
</props>
</property>
<property name="eventListeners">
<map>
<entry key="post-insert" value-ref="auditEventListener"/>
<entry key="post-update" value-ref="auditEventListener"/>
<entry key="post-delete" value-ref="auditEventListener"/>
<entry key="pre-collection-update" value-ref="auditEventListener"/>
<entry key="pre-collection-remove" value-ref="auditEventListener"/>
<entry key="post-collection-recreate" value-ref="auditEventListener"/>
</map>
</property>
</bean>
El interceptor:
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
..
public class DirtyCheckByPassInterceptor extends EmptyInterceptor {
public DirtyCheckByPassInterceptor() {
super();
}
/**
* Flags ALL properties as dirty, even if nothing has changed.
*/
@Override
public int[] findDirty(Object entity,
Serializable id,
Object[] currentState,
Object[] previousState,
String[] propertyNames,
Type[] types) {
int[] result = new int[ propertyNames.length ];
for (int i = 0; i < propertyNames.length; i++) {
result[ i ] = i;
}
return result;
}
}
ps: tenga en cuenta que este es un ejemplo simplificado. No funcionará de la caja, pero lo guiará hacia una solución de trabajo.
Tendrá un problema en esta categoría si está usando Envers ValidityAuditStrategy y tiene datos que han sido creados con la excepción de los Envers habilitados.
En nuestro caso (Hibernate 4.2.8.Final), una actualización de objeto básico arroja "No se puede actualizar la revisión anterior para la entidad y" (registrado como [org.hibernate.AssertionFailure] HHH000099).
Me tomó un tiempo para encontrar esta discusión/explicación por lo que la publicación cruzada:
- 1. Rellenar las tablas de la base de datos con una gran cantidad de datos de prueba
- 2. Entidades Hibernate sin tablas subyacentes
- 3. Java/Hibernate usando interfaces sobre las entidades
- 4. Django: elimine todos los datos de todas las tablas (pero conserve las tablas)
- 5. EnumConverter en las tablas de datos editables de las primefas
- 6. Partición de tablas existentes
- 7. Datos dinámicos en las tablas de pepino
- 8. agregando un ID único y PK a las tablas existentes
- 9. Eliminar datos de las tablas dependientes
- 10. Alterar las tablas de la base de datos en Django
- 11. Hibernate: crear automáticamente/actualización de las tablas de base de datos basado en clases de entidad
- 12. ¿Las tablas de datos ADO.Net tienen índices?
- 13. Uso de los criterios de Hibernate para recuperar datos de varias tablas sin configuración de asignación de entidades
- 14. SQL: elimine todos los datos de todas las tablas disponibles
- 15. Base de datos: insertar nuevas filas o actualizar las existentes?
- 16. generateDdl de HibernateJpaVendorAdapter no altera las tablas
- 17. Cambiar a las guías secuenciales (peine): ¿qué pasa con los datos existentes?
- 18. generar modelos de tablas existentes utilizando los carriles 3
- 19. Seleccionar de todas las tablas
- 20. Hable con las tablas de estilo de depósito de datos con ActiveRecord?
- 21. Cómo rellenar la aplicación web con los datos iniciales
- 22. EntityFramework muestra las entidades antes de guardar los cambios
- 23. Rails 3 I18n para las tablas de bases de datos
- 24. ¿Cómo puedo usar los datos JSON para rellenar las opciones de un cuadro de selección?
- 25. Datos principales: Obtener todas las entidades
- 26. ¿Cuál es la velocidad comparativa de las tablas temporales con las tablas físicas en SQL?
- 27. ¿Tiene una clase base común para las entidades Hibernate?
- 28. ¿Las entidades de servicios de tablas Azure tienen un equivalente de NonSerializedAttribute?
- 29. Cómo mostrar todas las tablas de múltiples bases de datos
- 30. Deshacer cambios en las entidades del marco de entidades
¿Cómo le va la auditoría para trabajar? Ni siquiera puedo llegar tan lejos :( –
Es muy simple, solo lea el manual bastante corto: http://www.jboss.org/files/envers/docs/index.html – danieljimenez
Me preguntaba sobre esto, pero necesita información de auditoría sobre el medio ambiente.Qué usuario y "cómo" hicieron el cambio, qué operación de usuario de alto nivel estaban haciendo que desencadenó el cambio. Esto es importante para poder ver los cambios explícitos frente a los cambios de "efectos secundarios". ¿Sabes si envers maneja esta necesidad? – Pat