HHH-7918 - Fix and test

This commit is contained in:
Lukasz Antoniak 2013-01-14 14:30:10 +01:00
parent 6062eb67ea
commit 2a9f3ad9ed
6 changed files with 107 additions and 6 deletions

View File

@ -427,7 +427,7 @@ public final class AuditMetadataGenerator {
ExtendedPropertyMapper propertyMapper = null;
String parentEntityName = null;
EntityConfiguration entityCfg = new EntityConfiguration(entityName, pc.getClassName(), idMapper, propertyMapper,
parentEntityName);
parentEntityName, auditingData.isUsingModifiedFlag());
notAuditedEntitiesConfigurations.put(entityName, entityCfg);
return;
}
@ -501,7 +501,7 @@ public final class AuditMetadataGenerator {
// Storing the generated configuration
EntityConfiguration entityCfg = new EntityConfiguration(auditEntityName, pc.getClassName(), idMapper,
propertyMapper, parentEntityName);
propertyMapper, parentEntityName, auditingData.isUsingModifiedFlag());
entitiesConfigurations.put(pc.getEntityName(), entityCfg);
}

View File

@ -86,6 +86,18 @@ public class ClassAuditingData implements AuditedPropertiesHolder {
return defaultAudited || properties.size() > 0;
}
/**
* @return {@code true} if any of the properties has modification flag enabled, {@code false} otherwise.
*/
public boolean isUsingModifiedFlag() {
for ( PropertyAuditingData prop : properties.values() ) {
if ( prop.isUsingModifiedFlag() ) {
return true;
}
}
return false;
}
public boolean contains(String propertyName) {
return properties.containsKey(propertyName);
}

View File

@ -42,14 +42,16 @@ public class EntityConfiguration {
// Maps from property name
private Map<String, RelationDescription> relations;
private String parentEntityName;
private boolean usingModifiedFlag;
public EntityConfiguration(String versionsEntityName, String entityClassName, IdMappingData idMappingData,
ExtendedPropertyMapper propertyMapper, String parentEntityName) {
ExtendedPropertyMapper propertyMapper, String parentEntityName, boolean usingModifiedFlag) {
this.versionsEntityName = versionsEntityName;
this.entityClassName = entityClassName;
this.idMappingData = idMappingData;
this.propertyMapper = propertyMapper;
this.parentEntityName = parentEntityName;
this.usingModifiedFlag = usingModifiedFlag;
this.relations = new HashMap<String, RelationDescription>();
}
@ -123,4 +125,11 @@ public class EntityConfiguration {
public String getEntityClassName() {
return entityClassName;
}
/**
* @return {@code true} if the entity or any of its properties use modification flag, {@code false} otherwise.
*/
public boolean isUsingModifiedFlag() {
return usingModifiedFlag;
}
}

View File

@ -72,5 +72,4 @@ public interface PropertyMapper {
void mapModifiedFlagsToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj);
void mapModifiedFlagsToMapForCollectionChange(String collectionPropertyName, Map<String, Object> data);
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.synchronization.work;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@ -38,10 +39,17 @@ public class ModWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
private final Map<String, Object> data;
private final boolean changes;
private final EntityPersister entityPersister;
private final Object[] oldState;
private final Object[] newState;
public ModWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg,
Serializable id, EntityPersister entityPersister, Object[] newState, Object[] oldState) {
super(sessionImplementor, entityName, verCfg, id, RevisionType.MOD);
this.entityPersister = entityPersister;
this.oldState = oldState;
this.newState = newState;
data = new HashMap<String, Object>();
changes = verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(sessionImplementor, data,
entityPersister.getPropertyNames(), newState, oldState);
@ -66,6 +74,14 @@ public class ModWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
}
public AuditWorkUnit merge(ModWorkUnit second) {
if ( verCfg.getEntCfg().get( getEntityName() ).isUsingModifiedFlag() ) {
// In case of multiple subsequent flushes within single transaction, modification flags need to be
// recalculated against initial and final state of the given entity.
return new ModWorkUnit(
second.sessionImplementor, second.getEntityName(), second.verCfg, second.id,
second.entityPersister, second.newState, this.oldState
);
}
return second;
}

View File

@ -0,0 +1,65 @@
package org.hibernate.envers.test.integration.modifiedflags;
import java.util.List;
import javax.persistence.EntityManager;
import org.junit.Test;
import org.hibernate.envers.test.Priority;
import org.hibernate.envers.test.integration.basic.BasicTestEntity1;
import org.hibernate.testing.TestForIssue;
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
import static org.hibernate.envers.test.tools.TestTools.makeList;
import static org.junit.Assert.assertEquals;
/**
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
@TestForIssue(jiraKey = "HHH-7918")
public class HasChangedManualFlush extends AbstractModifiedFlagsEntityTest {
private Integer id = null;
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { BasicTestEntity1.class };
}
@Test
@Priority(10)
public void initData() {
EntityManager em = getEntityManager();
// Revision 1
em.getTransaction().begin();
BasicTestEntity1 entity = new BasicTestEntity1( "str1", 1 );
em.persist( entity );
em.getTransaction().commit();
id = entity.getId();
// Revision 2 - both properties (str1 and long1) should be marked as modified.
em.getTransaction().begin();
entity = em.find( BasicTestEntity1.class, entity.getId() );
entity.setStr1( "str2" );
entity = em.merge( entity );
em.flush();
entity.setLong1( 2 );
entity = em.merge( entity );
em.flush();
em.getTransaction().commit();
em.close();
}
@Test
public void testHasChangedOnDoubleFlush() {
List list = queryForPropertyHasChanged( BasicTestEntity1.class, id, "str1" );
assertEquals( 2, list.size() );
assertEquals( makeList( 1, 2 ), extractRevisionNumbers( list ) );
list = queryForPropertyHasChanged( BasicTestEntity1.class, id, "long1" );
assertEquals( 2, list.size() );
assertEquals( makeList( 1, 2 ), extractRevisionNumbers( list ) );
}
}