Question

J'ajoute à une Envers les entités existantes mise en veille prolongée. Tout fonctionne en douceur jusqu'à présent dans la mesure où la vérification, mais l'interrogation est un autre problème parce que les tables de révision ne sont pas remplis avec les données existantes. Est-ce que quelqu'un d'autre déjà résolu ce problème? Peut-être que vous avez trouvé un moyen de remplir les tables de révision avec la table existante? Juste pensé que je demande, je suis sûr que d'autres trouveraient utile.

Était-ce utile?

La solution

Vous n'avez pas besoin.
AuditQuery vous permet d'obtenir à la fois RevisionEntity et révision des données par:

AuditQuery query = getAuditReader().createQuery()
                .forRevisionsOfEntity(YourAuditedEntity.class, false, false);

construira une requête qui renvoie une liste d'objets [3]. élément est Fisrt vos données, le second est l'entité de révision et le troisième est le type de révision.

Autres conseils

Nous avons peuplé les données initiales en exécutant une série de requêtes SQL premières pour simuler « l'insertion » toutes les entités existantes comme si elles venaient d'être créés en même temps. Par exemple:

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

Notez que l'indique un insert RevType valeur est 0 (par opposition à une modification).

Vous avez un problème dans cette catégorie si vous utilisez Envers ValidityAuditStrategy et ont des données qui a été créé autrement qu'avec Envers activés.

Dans notre cas (Hibernate 4.2.8.Final) une mise à jour de l'objet de base lancers francs « ne peut pas mettre à jour la révision précédente pour l'entité et » (connecté en tant que [org.hibernate.AssertionFailure] HHH000099).

Il m'a fallu un certain temps pour trouver cette discussion / explication si le cross-posting:

ValidityAuditStrategy avec aucun enregistrement d'audit

Nous avons résolu la question de peuplant les journaux d'audit avec les données existantes comme suit:

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 configuration de mes sources de données (via Spring):

<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>

L'intercepteur:

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: gardez à l'esprit que ceci est un exemple simplifié. Il ne fonctionnera pas hors de la boîte, mais il vous guidera vers une solution de travail.

Jetez un oeil à http://www.jboss.org /files/envers/docs/index.html#revisionlog

Fondamentalement, vous pouvez définir votre propre type de révision »en utilisant l'annotation @RevisionEntity, puis mettre en œuvre une interface RevisionListener pour insérer vos données d'audit supplémentaires, comme l'utilisateur et le fonctionnement actuels de haut niveau. En général, ceux qui sont tirés à partir du contexte ThreadLocal.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top