HHH-6605: Merging changes by Michal Skowronek. Thanks! Merge remote-tracking branch 'mskowron/change_info'
Conflicts: hibernate-envers/src/main/java/org/hibernate/envers/configuration/GlobalConfiguration.java hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/ComponentMetadataGenerator.java hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/reader/AuditedPropertiesReader.java hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/ComponentPropertyMapper.java hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/MultiPropertyMapper.java hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/PropertyMapper.java hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/SinglePropertyMapper.java hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/SubclassPropertyMapper.java hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/AbstractCollectionMapper.java hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/OneToOneNotOwningMapper.java hibernate-envers/src/main/java/org/hibernate/envers/event/BaseEnversCollectionEventListener.java hibernate-envers/src/main/java/org/hibernate/envers/query/criteria/AuditProperty.java hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/AddWorkUnit.java hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/CollectionChangeWorkUnit.java hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/DelWorkUnit.java hibernate-envers/src/main/java/org/hibernate/envers/synchronization/work/FakeBidirectionalRelationWorkUnit.java hibernate-envers/src/main/java/org/hibernate/envers/tools/Tools.java hibernate-envers/src/matrix/java/org/hibernate/envers/test/AbstractOneSessionTest.java hibernate-envers/src/matrix/java/org/hibernate/envers/test/AbstractSessionTest.java hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/components/relations/ManyToOneInComponent.java hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/components/relations/NotAuditedManyToOneInComponent.java hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/components/relations/OneToManyInComponent.java hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/entityNames/singleAssociatedAudited/SingleDomainObjectToMultipleTablesTest.java hibernate-envers/src/matrix/java/org/hibernate/envers/test/integration/inheritance/joined/notownedrelation/NotOwnedBidirectional.java
This commit is contained in:
commit
b109633b66
|
@ -267,6 +267,35 @@
|
||||||
and <xref linkend="envers-tracking-modified-entities-queries"/>.
|
and <xref linkend="envers-tracking-modified-entities-queries"/>.
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<property>org.hibernate.envers.global_with_modified_flag</property>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
false, can be individually overriden with <literal>@Audited(withModifiedFlag=true)</literal>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Should property modification flags be stored for all audited entities and all properties.
|
||||||
|
When set to true, for all properties an additional boolean column in the audit tables will
|
||||||
|
be created, filled with information if the given property changed in the given revision.
|
||||||
|
When set to false, such column can be added to selected entities or properties using the
|
||||||
|
<literal>@Audited</literal> annotation.
|
||||||
|
For more information refer to <xref linkend="envers-tracking-properties-changes"/>
|
||||||
|
and <xref linkend="envers-envers-tracking-properties-changes-queries"/>.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<property>org.hibernate.envers.modified_flag_suffix</property>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
_MOD
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
The suffix for columns storing "Modified Flags".
|
||||||
|
For example: a property called "age", will by default get modified flag with column name "age_MOD".
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
@ -278,6 +307,12 @@
|
||||||
<listitem>
|
<listitem>
|
||||||
org.hibernate.envers.track_entities_changed_in_revision
|
org.hibernate.envers.track_entities_changed_in_revision
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
org.hibernate.envers.using_modified_flag
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
org.hibernate.envers.modified_flag_suffix
|
||||||
|
</listitem>
|
||||||
</orderedlist>
|
</orderedlist>
|
||||||
</para>
|
</para>
|
||||||
</important>
|
</important>
|
||||||
|
@ -627,6 +662,54 @@ Set<ModifiedEntityTypeEntity> modifiedEntityTypes = revEntity.getModifiedEntityT
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="envers-tracking-properties-changes">
|
||||||
|
<title>Tracking entity changes at property level</title>
|
||||||
|
<para>
|
||||||
|
By default the only information stored by Envers are revisions of modified entities.
|
||||||
|
This approach lets user create audit queries based on historical values of entity's properties.
|
||||||
|
|
||||||
|
Sometimes it is useful to store additional metadata for each revision, when you are interested also in
|
||||||
|
the type of changes, not only about the resulting values. The feature described in
|
||||||
|
<xref linkend="envers-tracking-modified-entities-revchanges"/>
|
||||||
|
makes it possible to tell which entities were modified in given revision.
|
||||||
|
|
||||||
|
Feature described here takes it one step further. "Modification Flags" enable Envers to track which
|
||||||
|
properties of audited entities were modified in a given revision.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Tracking entity changes at property level can be enabled by:
|
||||||
|
</para>
|
||||||
|
<orderedlist>
|
||||||
|
<listitem>
|
||||||
|
setting
|
||||||
|
<property>org.hibernate.envers.global_with_modified_flag</property>
|
||||||
|
configuration property to
|
||||||
|
<literal>true</literal>.
|
||||||
|
This global switch will cause adding modification flags for all audited
|
||||||
|
properties in all audited entities.
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
using <literal>@Audited(withModifiedFlag=true)</literal>
|
||||||
|
on a property or on an entity.
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
|
<para>
|
||||||
|
The trade-off coming with this functionality is an increased size of
|
||||||
|
audit tables and a very little, almost negligible, performance drop
|
||||||
|
during audit writes. This is due to the fact that every tracked
|
||||||
|
property has to have an accompanying boolean column in the
|
||||||
|
schema that stores information about the property's modifications. Of
|
||||||
|
course it is Envers' job to fill these columns accordingly - no additional work by the
|
||||||
|
developer is required. Because of costs mentioned, it is recommended
|
||||||
|
to enable the feature selectively, when needed with use of the
|
||||||
|
granular configuration means described above.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To see how "Modified Flags" can be utilized, check out the very
|
||||||
|
simple query API that uses them: <xref linkend="envers-envers-tracking-properties-changes-queries"/>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section id="envers-queries">
|
<section id="envers-queries">
|
||||||
|
|
||||||
<title>Queries</title>
|
<title>Queries</title>
|
||||||
|
@ -816,6 +899,78 @@ query.add(AuditEntity.relatedId("address").eq(relatedEntityId));]]></programlist
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="envers-envers-tracking-properties-changes-queries">
|
||||||
|
|
||||||
|
<title>Querying for revisions of entity that modified given property</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For the two types of queries described above it's possible to use
|
||||||
|
special Audit criteria called
|
||||||
|
<literal>hasChanged()</literal>
|
||||||
|
and
|
||||||
|
<literal>hasNotChanged()</literal>
|
||||||
|
that makes use of the functionality
|
||||||
|
described in <xref linkend="envers-tracking-properties-changes"/>.
|
||||||
|
They're best suited for vertical queries,
|
||||||
|
however existing API doesn't restrict their usage for horizontal
|
||||||
|
ones.
|
||||||
|
|
||||||
|
Let's have a look at following examples:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<programlisting><![CDATA[
|
||||||
|
AuditQuery query = getAuditReader().createQuery()
|
||||||
|
.forRevisionsOfEntity(MyEntity.class, false, true)
|
||||||
|
.add(AuditEntity.id().eq(id));
|
||||||
|
.add(AuditEntity.property("actualDate").hasChanged())]]>
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This query will return all revisions of MyEntity with given id,
|
||||||
|
where the
|
||||||
|
<property>actualDate</property>
|
||||||
|
property has been changed.
|
||||||
|
Using this query we won't get all other revisions in which
|
||||||
|
<property>actualDate</property>
|
||||||
|
wasn't touched. Of course nothing prevents user from combining
|
||||||
|
hasChanged condition with some additional criteria - add method
|
||||||
|
can be used here in a normal way.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<programlisting><![CDATA[
|
||||||
|
AuditQuery query = getAuditReader().createQuery()
|
||||||
|
.forEntitiesAtRevision(MyEntity.class, revisionNumber)
|
||||||
|
.add(AuditEntity.property("prop1").hasChanged())
|
||||||
|
.add(AuditEntity.property("prop2").hasNotChanged());]]>
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This query will return horizontal slice for MyEntity at the time
|
||||||
|
revisionNumber was generated. It will be limited to revisions
|
||||||
|
that modified
|
||||||
|
<property>prop1</property>
|
||||||
|
but not <property>prop2</property>.
|
||||||
|
Note that the result set will usually also contain revisions
|
||||||
|
with numbers lower than the revisionNumber, so we cannot read
|
||||||
|
this query as "Give me all MyEntities changed in revisionNumber
|
||||||
|
with
|
||||||
|
<property>prop1</property>
|
||||||
|
modified and
|
||||||
|
<property>prop2</property>
|
||||||
|
untouched". To get such result we have to use the
|
||||||
|
<literal>forEntitiesModifiedAtRevision</literal> query:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<programlisting><![CDATA[
|
||||||
|
AuditQuery query = getAuditReader().createQuery()
|
||||||
|
.forEntitiesModifiedAtRevision(MyEntity.class, revisionNumber)
|
||||||
|
.add(AuditEntity.property("prop1").hasChanged())
|
||||||
|
.add(AuditEntity.property("prop2").hasNotChanged());]]>
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<section id="envers-tracking-modified-entities-queries">
|
<section id="envers-tracking-modified-entities-queries">
|
||||||
<title>Querying for entities modified in a given revision</title>
|
<title>Querying for entities modified in a given revision</title>
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -33,6 +33,7 @@ import java.lang.annotation.Target;
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Tomasz Bech
|
* @author Tomasz Bech
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||||
|
@ -59,4 +60,11 @@ public @interface Audited {
|
||||||
* @deprecated Use {@code @AuditOverride(forClass=SomeEntity.class)} instead.
|
* @deprecated Use {@code @AuditOverride(forClass=SomeEntity.class)} instead.
|
||||||
*/
|
*/
|
||||||
Class[] auditParents() default {};
|
Class[] auditParents() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Should a modification flag be stored for each property in the annotated class or for the annotated
|
||||||
|
* property. The flag stores information if a property has been changed at a given revision.
|
||||||
|
* This can be used for example in queries.
|
||||||
|
*/
|
||||||
|
boolean withModifiedFlag() default false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,14 @@ import static org.hibernate.envers.tools.Tools.getProperty;
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Nicolas Doroskevich
|
* @author Nicolas Doroskevich
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class GlobalConfiguration {
|
public class GlobalConfiguration {
|
||||||
// Should a revision be generated when a not-owned relation field changes
|
public static final String GLOBAL_WITH_MODIFIED_FLAG_PROPERTY = "org.hibernate.envers.global_with_modified_flag";
|
||||||
|
public static final String MODIFIED_FLAG_SUFFIX_PROPERTY = "org.hibernate.envers.modified_flag_suffix";
|
||||||
|
public static final String DEFAULT_MODIFIED_FLAG_SUFFIX = "_MOD";
|
||||||
|
|
||||||
|
// Should a revision be generated when a not-owned relation field changes
|
||||||
private final boolean generateRevisionsForCollections;
|
private final boolean generateRevisionsForCollections;
|
||||||
|
|
||||||
// Should the optimistic locking property of an entity be considered unversioned
|
// Should the optimistic locking property of an entity be considered unversioned
|
||||||
|
@ -56,6 +61,15 @@ public class GlobalConfiguration {
|
||||||
// Revision listener class name.
|
// Revision listener class name.
|
||||||
private final Class<? extends RevisionListener> revisionListenerClass;
|
private final Class<? extends RevisionListener> revisionListenerClass;
|
||||||
|
|
||||||
|
// Should Envers use modified property flags by default
|
||||||
|
private boolean globalWithModifiedFlag;
|
||||||
|
|
||||||
|
// Indicates that user defined global behavior for modified flags feature
|
||||||
|
private boolean hasGlobalSettingForWithModifiedFlag;
|
||||||
|
|
||||||
|
// Suffix to be used for modified flags columns
|
||||||
|
private String modifiedFlagSuffix;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Which operator to use in correlated subqueries (when we want a property to be equal to the result of
|
Which operator to use in correlated subqueries (when we want a property to be equal to the result of
|
||||||
a correlated subquery, for example: e.p <operator> (select max(e2.p) where e2.p2 = e.p2 ...).
|
a correlated subquery, for example: e.p <operator> (select max(e2.p) where e2.p2 = e.p2 ...).
|
||||||
|
@ -95,7 +109,20 @@ public class GlobalConfiguration {
|
||||||
"false");
|
"false");
|
||||||
trackEntitiesChangedInRevisionEnabled = Boolean.parseBoolean(trackEntitiesChangedInRevisionEnabledStr);
|
trackEntitiesChangedInRevisionEnabled = Boolean.parseBoolean(trackEntitiesChangedInRevisionEnabledStr);
|
||||||
|
|
||||||
String revisionListenerClassName = properties.getProperty("org.hibernate.envers.revision_listener", null);
|
hasGlobalSettingForWithModifiedFlag =
|
||||||
|
properties.getProperty(GLOBAL_WITH_MODIFIED_FLAG_PROPERTY) != null;
|
||||||
|
String usingModifiedFlagStr = getProperty(properties,
|
||||||
|
GLOBAL_WITH_MODIFIED_FLAG_PROPERTY,
|
||||||
|
GLOBAL_WITH_MODIFIED_FLAG_PROPERTY,
|
||||||
|
"false");
|
||||||
|
globalWithModifiedFlag = Boolean.parseBoolean(usingModifiedFlagStr);
|
||||||
|
|
||||||
|
modifiedFlagSuffix =
|
||||||
|
getProperty(properties, MODIFIED_FLAG_SUFFIX_PROPERTY,
|
||||||
|
MODIFIED_FLAG_SUFFIX_PROPERTY,
|
||||||
|
DEFAULT_MODIFIED_FLAG_SUFFIX);
|
||||||
|
|
||||||
|
String revisionListenerClassName = properties.getProperty("org.hibernate.envers.revision_listener", null);
|
||||||
if (revisionListenerClassName != null) {
|
if (revisionListenerClassName != null) {
|
||||||
try {
|
try {
|
||||||
revisionListenerClass = (Class<? extends RevisionListener>) Thread.currentThread().getContextClassLoader().loadClass(revisionListenerClassName);
|
revisionListenerClass = (Class<? extends RevisionListener>) Thread.currentThread().getContextClassLoader().loadClass(revisionListenerClassName);
|
||||||
|
@ -142,4 +169,16 @@ public class GlobalConfiguration {
|
||||||
public Class<? extends RevisionListener> getRevisionListenerClass() {
|
public Class<? extends RevisionListener> getRevisionListenerClass() {
|
||||||
return revisionListenerClass;
|
return revisionListenerClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasSettingForUsingModifiedFlag() {
|
||||||
|
return hasGlobalSettingForWithModifiedFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGlobalWithModifiedFlag() {
|
||||||
|
return globalWithModifiedFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModifiedFlagSuffix() {
|
||||||
|
return modifiedFlagSuffix;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ import org.hibernate.type.Type;
|
||||||
* @author Stephanie Pau at Markit Group Plc
|
* @author Stephanie Pau at Markit Group Plc
|
||||||
* @author Hernán Chanfreau
|
* @author Hernán Chanfreau
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public final class AuditMetadataGenerator {
|
public final class AuditMetadataGenerator {
|
||||||
|
|
||||||
|
@ -166,54 +167,79 @@ public final class AuditMetadataGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
|
private void addValueInFirstPass(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
|
||||||
EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData,
|
EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData,
|
||||||
boolean insertable, boolean firstPass) {
|
boolean insertable, boolean processModifiedFlag) {
|
||||||
Type type = value.getType();
|
Type type = value.getType();
|
||||||
|
|
||||||
// only first pass
|
if (basicMetadataGenerator.addBasic(parent, propertyAuditingData, value, currentMapper, insertable, false)) {
|
||||||
if (firstPass) {
|
// The property was mapped by the basic generator.
|
||||||
if (basicMetadataGenerator.addBasic(parent, propertyAuditingData, value, currentMapper,
|
} else if (type instanceof ComponentType) {
|
||||||
insertable, false)) {
|
componentMetadataGenerator.addComponent(parent, propertyAuditingData, value, currentMapper,
|
||||||
// The property was mapped by the basic generator.
|
entityName, xmlMappingData, true);
|
||||||
return;
|
} else {
|
||||||
}
|
if (!processedInSecondPass(type)) {
|
||||||
}
|
// If we got here in the first pass, it means the basic mapper didn't map it, and none of the
|
||||||
|
// above branches either.
|
||||||
|
throwUnsupportedTypeException(type, entityName, propertyAuditingData.getName());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addModifiedFlagIfNeeded(parent, propertyAuditingData, processModifiedFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processedInSecondPass(Type type) {
|
||||||
|
return type instanceof ComponentType || type instanceof ManyToOneType ||
|
||||||
|
type instanceof OneToOneType || type instanceof CollectionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addValueInSecondPass(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
|
||||||
|
EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData,
|
||||||
|
boolean insertable, boolean processModifiedFlag) {
|
||||||
|
Type type = value.getType();
|
||||||
|
|
||||||
if (type instanceof ComponentType) {
|
if (type instanceof ComponentType) {
|
||||||
// both passes
|
|
||||||
componentMetadataGenerator.addComponent(parent, propertyAuditingData, value, currentMapper,
|
componentMetadataGenerator.addComponent(parent, propertyAuditingData, value, currentMapper,
|
||||||
entityName, xmlMappingData, firstPass);
|
entityName, xmlMappingData, false);
|
||||||
|
return;// mod flag field has been already generated in first pass
|
||||||
} else if (type instanceof ManyToOneType) {
|
} else if (type instanceof ManyToOneType) {
|
||||||
// only second pass
|
toOneRelationMetadataGenerator.addToOne(parent, propertyAuditingData, value, currentMapper,
|
||||||
if (!firstPass) {
|
entityName, insertable);
|
||||||
toOneRelationMetadataGenerator.addToOne(parent, propertyAuditingData, value, currentMapper,
|
} else if (type instanceof OneToOneType) {
|
||||||
entityName, insertable);
|
toOneRelationMetadataGenerator.addOneToOneNotOwning(propertyAuditingData, value,
|
||||||
}
|
currentMapper, entityName);
|
||||||
} else if (type instanceof OneToOneType) {
|
} else if (type instanceof CollectionType) {
|
||||||
// only second pass
|
CollectionMetadataGenerator collectionMetadataGenerator = new CollectionMetadataGenerator(this,
|
||||||
if (!firstPass) {
|
(Collection) value, currentMapper, entityName, xmlMappingData,
|
||||||
toOneRelationMetadataGenerator.addOneToOneNotOwning(propertyAuditingData, value,
|
propertyAuditingData);
|
||||||
currentMapper, entityName);
|
collectionMetadataGenerator.addCollection();
|
||||||
}
|
} else {
|
||||||
} else if (type instanceof CollectionType) {
|
return;
|
||||||
// only second pass
|
}
|
||||||
if (!firstPass) {
|
addModifiedFlagIfNeeded(parent, propertyAuditingData, processModifiedFlag);
|
||||||
CollectionMetadataGenerator collectionMetadataGenerator = new CollectionMetadataGenerator(this,
|
}
|
||||||
(Collection) value, currentMapper, entityName, xmlMappingData,
|
|
||||||
propertyAuditingData);
|
|
||||||
collectionMetadataGenerator.addCollection();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (firstPass) {
|
|
||||||
// If we got here in the first pass, it means the basic mapper didn't map it, and none of the
|
|
||||||
// above branches either.
|
|
||||||
throwUnsupportedTypeException(type, entityName, propertyAuditingData.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
|
private void addModifiedFlagIfNeeded(Element parent, PropertyAuditingData propertyAuditingData, boolean processModifiedFlag) {
|
||||||
|
if (processModifiedFlag && propertyAuditingData.isUsingModifiedFlag()) {
|
||||||
|
MetadataTools.addModifiedFlagProperty(parent,
|
||||||
|
propertyAuditingData.getName(),
|
||||||
|
globalCfg.getModifiedFlagSuffix());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
|
||||||
|
EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData,
|
||||||
|
boolean insertable, boolean firstPass, boolean processModifiedFlag) {
|
||||||
|
if (firstPass) {
|
||||||
|
addValueInFirstPass(parent, value, currentMapper, entityName,
|
||||||
|
xmlMappingData, propertyAuditingData, insertable, processModifiedFlag);
|
||||||
|
} else {
|
||||||
|
addValueInSecondPass(parent, value, currentMapper, entityName,
|
||||||
|
xmlMappingData, propertyAuditingData, insertable, processModifiedFlag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
|
||||||
ClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData,
|
ClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData,
|
||||||
boolean firstPass) {
|
boolean firstPass) {
|
||||||
while (properties.hasNext()) {
|
while (properties.hasNext()) {
|
||||||
|
@ -222,7 +248,7 @@ public final class AuditMetadataGenerator {
|
||||||
PropertyAuditingData propertyAuditingData = auditingData.getPropertyAuditingData(propertyName);
|
PropertyAuditingData propertyAuditingData = auditingData.getPropertyAuditingData(propertyName);
|
||||||
if (propertyAuditingData != null) {
|
if (propertyAuditingData != null) {
|
||||||
addValue(parent, property.getValue(), currentMapper, entityName, xmlMappingData, propertyAuditingData,
|
addValue(parent, property.getValue(), currentMapper, entityName, xmlMappingData, propertyAuditingData,
|
||||||
property.isInsertable(), firstPass);
|
property.isInsertable(), firstPass, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ public final class ComponentMetadataGenerator {
|
||||||
// Checking if that property is audited
|
// Checking if that property is audited
|
||||||
if (componentPropertyAuditingData != null) {
|
if (componentPropertyAuditingData != null) {
|
||||||
mainGenerator.addValue(parent, property.getValue(), componentMapper, entityName, xmlMappingData,
|
mainGenerator.addValue(parent, property.getValue(), componentMapper, entityName, xmlMappingData,
|
||||||
componentPropertyAuditingData, property.isInsertable(), firstPass);
|
componentPropertyAuditingData, property.isInsertable(), firstPass, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,11 @@ import org.hibernate.mapping.Formula;
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class MetadataTools {
|
public class MetadataTools {
|
||||||
public static Element addNativelyGeneratedId(Element parent, String name, String type) {
|
|
||||||
|
public static Element addNativelyGeneratedId(Element parent, String name, String type) {
|
||||||
Element id_mapping = parent.addElement("id");
|
Element id_mapping = parent.addElement("id");
|
||||||
id_mapping.addAttribute("name", name).addAttribute("type", type);
|
id_mapping.addAttribute("name", name).addAttribute("type", type);
|
||||||
|
|
||||||
|
@ -73,7 +75,15 @@ public class MetadataTools {
|
||||||
return addProperty(parent, name, type, insertable, false, key);
|
return addProperty(parent, name, type, insertable, false, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addOrModifyAttribute(Element parent, String name, String value) {
|
public static Element addModifiedFlagProperty(Element parent, String propertyName, String suffix) {
|
||||||
|
return addProperty(parent, getModifiedFlagPropertyName(propertyName, suffix), "boolean", true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getModifiedFlagPropertyName(String propertyName, String suffix) {
|
||||||
|
return propertyName + suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addOrModifyAttribute(Element parent, String name, String value) {
|
||||||
Attribute attribute = parent.attribute(name);
|
Attribute attribute = parent.attribute(name);
|
||||||
if (attribute == null) {
|
if (attribute == null) {
|
||||||
parent.addAttribute(name, value);
|
parent.addAttribute(name, value);
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.envers.ModificationStore;
|
||||||
import org.hibernate.envers.NotAudited;
|
import org.hibernate.envers.NotAudited;
|
||||||
import org.hibernate.envers.RelationTargetAuditMode;
|
import org.hibernate.envers.RelationTargetAuditMode;
|
||||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
|
import org.hibernate.envers.configuration.metadata.MetadataTools;
|
||||||
import org.hibernate.envers.tools.MappingTools;
|
import org.hibernate.envers.tools.MappingTools;
|
||||||
import org.hibernate.envers.tools.StringTools;
|
import org.hibernate.envers.tools.StringTools;
|
||||||
import org.hibernate.envers.tools.Tools;
|
import org.hibernate.envers.tools.Tools;
|
||||||
|
@ -43,6 +44,7 @@ import static org.hibernate.envers.tools.Tools.newHashSet;
|
||||||
* @author Erik-Berndt Scheper
|
* @author Erik-Berndt Scheper
|
||||||
* @author Hern&aacut;n Chanfreau
|
* @author Hern&aacut;n Chanfreau
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class AuditedPropertiesReader {
|
public class AuditedPropertiesReader {
|
||||||
protected final ModificationStore defaultStore;
|
protected final ModificationStore defaultStore;
|
||||||
|
@ -392,9 +394,13 @@ public class AuditedPropertiesReader {
|
||||||
if(!this.checkAudited(property, propertyData, allClassAudited)){
|
if(!this.checkAudited(property, propertyData, allClassAudited)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
propertyData.setName(propertyNamePrefix + property.getName());
|
String propertyName = propertyNamePrefix + property.getName();
|
||||||
|
propertyData.setName(propertyName);
|
||||||
|
propertyData.setModifiedFlagName(
|
||||||
|
MetadataTools.getModifiedFlagPropertyName(
|
||||||
|
propertyName,
|
||||||
|
globalCfg.getModifiedFlagSuffix()));
|
||||||
propertyData.setBeanName(property.getName());
|
propertyData.setBeanName(property.getName());
|
||||||
propertyData.setAccessType(accessType);
|
propertyData.setAccessType(accessType);
|
||||||
|
|
||||||
|
@ -409,7 +415,7 @@ public class AuditedPropertiesReader {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected boolean checkAudited(XProperty property,
|
protected boolean checkAudited(XProperty property,
|
||||||
PropertyAuditingData propertyData, Audited allClassAudited) {
|
PropertyAuditingData propertyData, Audited allClassAudited) {
|
||||||
// Checking if this property is explicitly audited or if all properties are.
|
// Checking if this property is explicitly audited or if all properties are.
|
||||||
|
@ -422,13 +428,19 @@ public class AuditedPropertiesReader {
|
||||||
if (aud != null) {
|
if (aud != null) {
|
||||||
propertyData.setStore(aud.modStore());
|
propertyData.setStore(aud.modStore());
|
||||||
propertyData.setRelationTargetAuditMode(aud.targetAuditMode());
|
propertyData.setRelationTargetAuditMode(aud.targetAuditMode());
|
||||||
|
propertyData.setUsingModifiedFlag(checkUsingModifiedFlag(aud));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPropertyAuditMappedBy(XProperty property, PropertyAuditingData propertyData) {
|
protected boolean checkUsingModifiedFlag(Audited aud) {
|
||||||
|
return globalCfg.hasSettingForUsingModifiedFlag() ?
|
||||||
|
globalCfg.isGlobalWithModifiedFlag() : aud.withModifiedFlag();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPropertyAuditMappedBy(XProperty property, PropertyAuditingData propertyData) {
|
||||||
AuditMappedBy auditMappedBy = property.getAnnotation(AuditMappedBy.class);
|
AuditMappedBy auditMappedBy = property.getAnnotation(AuditMappedBy.class);
|
||||||
if (auditMappedBy != null) {
|
if (auditMappedBy != null) {
|
||||||
propertyData.setAuditMappedBy(auditMappedBy.mappedBy());
|
propertyData.setAuditMappedBy(auditMappedBy.mappedBy());
|
||||||
|
@ -507,6 +519,7 @@ public class AuditedPropertiesReader {
|
||||||
public ModificationStore modStore() { return ModificationStore.FULL; }
|
public ModificationStore modStore() { return ModificationStore.FULL; }
|
||||||
public RelationTargetAuditMode targetAuditMode() { return RelationTargetAuditMode.AUDITED; }
|
public RelationTargetAuditMode targetAuditMode() { return RelationTargetAuditMode.AUDITED; }
|
||||||
public Class[] auditParents() { return new Class[0]; }
|
public Class[] auditParents() { return new Class[0]; }
|
||||||
|
public boolean withModifiedFlag() { return false; }
|
||||||
public Class<? extends Annotation> annotationType() { return this.getClass(); }
|
public Class<? extends Annotation> annotationType() { return this.getClass(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
* Reads the audited properties for components.
|
* Reads the audited properties for components.
|
||||||
*
|
*
|
||||||
* @author Hern&aacut;n Chanfreau
|
* @author Hern&aacut;n Chanfreau
|
||||||
*
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class ComponentAuditedPropertiesReader extends AuditedPropertiesReader {
|
public class ComponentAuditedPropertiesReader extends AuditedPropertiesReader {
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ public class ComponentAuditedPropertiesReader extends AuditedPropertiesReader {
|
||||||
if (aud != null) {
|
if (aud != null) {
|
||||||
propertyData.setStore(aud.modStore());
|
propertyData.setStore(aud.modStore());
|
||||||
propertyData.setRelationTargetAuditMode(aud.targetAuditMode());
|
propertyData.setRelationTargetAuditMode(aud.targetAuditMode());
|
||||||
|
propertyData.setUsingModifiedFlag(checkUsingModifiedFlag(aud));
|
||||||
} else {
|
} else {
|
||||||
propertyData.setStore(ModificationStore.FULL);
|
propertyData.setStore(ModificationStore.FULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.envers.entities.PropertyData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class PropertyAuditingData {
|
public class PropertyAuditingData {
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -48,6 +49,8 @@ public class PropertyAuditingData {
|
||||||
private String auditMappedBy;
|
private String auditMappedBy;
|
||||||
private String positionMappedBy;
|
private String positionMappedBy;
|
||||||
private boolean forceInsertable;
|
private boolean forceInsertable;
|
||||||
|
private boolean usingModifiedFlag;
|
||||||
|
private String modifiedFlagName;
|
||||||
|
|
||||||
public PropertyAuditingData() {
|
public PropertyAuditingData() {
|
||||||
}
|
}
|
||||||
|
@ -115,7 +118,8 @@ public class PropertyAuditingData {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyData getPropertyData() {
|
public PropertyData getPropertyData() {
|
||||||
return new PropertyData(name, beanName, accessType, store);
|
return new PropertyData(name, beanName, accessType, store,
|
||||||
|
usingModifiedFlag, modifiedFlagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AuditOverride> getAuditingOverrides() {
|
public List<AuditOverride> getAuditingOverrides() {
|
||||||
|
@ -146,7 +150,19 @@ public class PropertyAuditingData {
|
||||||
this.forceInsertable = forceInsertable;
|
this.forceInsertable = forceInsertable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAuditingOverride(AuditOverride annotation) {
|
public boolean isUsingModifiedFlag() {
|
||||||
|
return usingModifiedFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsingModifiedFlag(boolean usingModifiedFlag) {
|
||||||
|
this.usingModifiedFlag = usingModifiedFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModifiedFlagName(String modifiedFlagName) {
|
||||||
|
this.modifiedFlagName = modifiedFlagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAuditingOverride(AuditOverride annotation) {
|
||||||
if (annotation != null) {
|
if (annotation != null) {
|
||||||
String overrideName = annotation.name();
|
String overrideName = annotation.name();
|
||||||
boolean present = false;
|
boolean present = false;
|
||||||
|
|
|
@ -22,13 +22,18 @@
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.envers.entities;
|
package org.hibernate.envers.entities;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration of the user entities: property mapping of the entities, relations, inheritance.
|
* Configuration of the user entities: property mapping of the entities, relations, inheritance.
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Hernán Chanfreau
|
* @author Hernán Chanfreau
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class EntitiesConfigurations {
|
public class EntitiesConfigurations {
|
||||||
private Map<String, EntityConfiguration> entitiesConfigurations;
|
private Map<String, EntityConfiguration> entitiesConfigurations;
|
||||||
|
@ -113,4 +118,44 @@ public class EntitiesConfigurations {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Collection<RelationDescription> getRelationDescriptions(String entityName) {
|
||||||
|
EntityConfiguration entCfg = entitiesConfigurations.get(entityName);
|
||||||
|
Collection<RelationDescription> descriptions = new ArrayList<RelationDescription>();
|
||||||
|
if (entCfg.getParentEntityName() != null) {
|
||||||
|
// collect descriptions from super classes
|
||||||
|
descriptions.addAll(getRelationDescriptions(entCfg.getParentEntityName()));
|
||||||
|
}
|
||||||
|
for (RelationDescription relationDescription : entCfg.getRelationsIterator()) {
|
||||||
|
descriptions.add(relationDescription);
|
||||||
|
}
|
||||||
|
return descriptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addWithParentEntityNames(String entityName, Set<String> entityNames) {
|
||||||
|
entityNames.add(entityName);
|
||||||
|
EntityConfiguration entCfg = entitiesConfigurations.get(entityName);
|
||||||
|
if (entCfg.getParentEntityName() != null) {
|
||||||
|
// collect descriptions from super classes
|
||||||
|
addWithParentEntityNames(entCfg.getParentEntityName(), entityNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getEntityAndParentsNames(String entityName) {
|
||||||
|
Set<String> names = new HashSet<String>();
|
||||||
|
addWithParentEntityNames(entityName, names);
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getToPropertyNames(String fromEntityName, String fromPropertyName, String toEntityName) {
|
||||||
|
Set<String> entityAndParentsNames = getEntityAndParentsNames(fromEntityName);
|
||||||
|
Set<String> toPropertyNames = new HashSet<String>();
|
||||||
|
for (RelationDescription relationDescription : getRelationDescriptions(toEntityName)) {
|
||||||
|
String relToEntityName = relationDescription.getToEntityName();
|
||||||
|
String mappedByPropertyName = relationDescription.getMappedByPropertyName();
|
||||||
|
if (entityAndParentsNames.contains(relToEntityName) && mappedByPropertyName.equals(fromPropertyName)) {
|
||||||
|
toPropertyNames.add(relationDescription.getFromPropertyName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toPropertyNames;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ public class PropertyData {
|
||||||
private final String beanName;
|
private final String beanName;
|
||||||
private final String accessType;
|
private final String accessType;
|
||||||
private final ModificationStore store;
|
private final ModificationStore store;
|
||||||
|
private boolean usingModifiedFlag;
|
||||||
|
private String modifiedFlagName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies the given property data, except the name.
|
* Copies the given property data, except the name.
|
||||||
|
@ -62,6 +64,19 @@ public class PropertyData {
|
||||||
this.store = store;
|
this.store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name Name of the property.
|
||||||
|
* @param beanName Name of the property in the bean.
|
||||||
|
* @param accessType Accessor type for this property.
|
||||||
|
* @param store How this property should be stored.
|
||||||
|
* @param usingModifiedFlag Defines if field changes should be tracked
|
||||||
|
*/
|
||||||
|
public PropertyData(String name, String beanName, String accessType, ModificationStore store, boolean usingModifiedFlag, String modifiedFlagName) {
|
||||||
|
this(name, beanName, accessType, store);
|
||||||
|
this.usingModifiedFlag = usingModifiedFlag;
|
||||||
|
this.modifiedFlagName = modifiedFlagName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +93,14 @@ public class PropertyData {
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUsingModifiedFlag() {
|
||||||
|
return usingModifiedFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModifiedFlagPropertyName() {
|
||||||
|
return modifiedFlagName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -89,6 +112,7 @@ public class PropertyData {
|
||||||
if (beanName != null ? !beanName.equals(that.beanName) : that.beanName != null) return false;
|
if (beanName != null ? !beanName.equals(that.beanName) : that.beanName != null) return false;
|
||||||
if (name != null ? !name.equals(that.name) : that.name != null) return false;
|
if (name != null ? !name.equals(that.name) : that.name != null) return false;
|
||||||
if (store != that.store) return false;
|
if (store != that.store) return false;
|
||||||
|
if (usingModifiedFlag != that.usingModifiedFlag) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -99,6 +123,7 @@ public class PropertyData {
|
||||||
result = 31 * result + (beanName != null ? beanName.hashCode() : 0);
|
result = 31 * result + (beanName != null ? beanName.hashCode() : 0);
|
||||||
result = 31 * result + (accessType != null ? accessType.hashCode() : 0);
|
result = 31 * result + (accessType != null ? accessType.hashCode() : 0);
|
||||||
result = 31 * result + (store != null ? store.hashCode() : 0);
|
result = 31 * result + (store != null ? store.hashCode() : 0);
|
||||||
|
result = 31 * result + (usingModifiedFlag ? 1 : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.envers.entities.mapper;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
|
@ -38,6 +39,7 @@ import org.hibernate.property.Setter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class ComponentPropertyMapper implements PropertyMapper, CompositeMapperBuilder {
|
public class ComponentPropertyMapper implements PropertyMapper, CompositeMapperBuilder {
|
||||||
private final PropertyData propertyData;
|
private final PropertyData propertyData;
|
||||||
|
@ -66,7 +68,29 @@ public class ComponentPropertyMapper implements PropertyMapper, CompositeMapperB
|
||||||
return delegate.mapToMapFromEntity(session, data, newObj, oldObj);
|
return delegate.mapToMapFromEntity(session, data, newObj, oldObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||||
|
if (propertyData.isUsingModifiedFlag()) {
|
||||||
|
data.put(propertyData.getModifiedFlagPropertyName(),
|
||||||
|
delegate.mapToMapFromEntity(session, new HashMap<String, Object>(), newObj, oldObj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapForCollectionChange(String collectionPropertyName, Map<String, Object> data) {
|
||||||
|
if (propertyData.isUsingModifiedFlag()) {
|
||||||
|
boolean hasModifiedCollection = false;
|
||||||
|
for (PropertyData propData : delegate.getProperties().keySet()) {
|
||||||
|
if (collectionPropertyName.equals(propData.getName())) {
|
||||||
|
hasModifiedCollection = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.put(propertyData.getModifiedFlagPropertyName(), hasModifiedCollection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
|
||||||
if (data == null || obj == null) {
|
if (data == null || obj == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,14 @@ import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
import org.hibernate.envers.entities.PropertyData;
|
import org.hibernate.envers.entities.PropertyData;
|
||||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||||
import org.hibernate.envers.tools.MappingTools;
|
import org.hibernate.envers.tools.MappingTools;
|
||||||
|
import org.hibernate.envers.tools.Pair;
|
||||||
import org.hibernate.envers.tools.Tools;
|
import org.hibernate.envers.tools.Tools;
|
||||||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||||
import org.hibernate.property.Getter;
|
import org.hibernate.property.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
||||||
protected final Map<PropertyData, PropertyMapper> properties;
|
protected final Map<PropertyData, PropertyMapper> properties;
|
||||||
|
@ -80,9 +82,11 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
||||||
String propertyName = propertyNames[i];
|
String propertyName = propertyNames[i];
|
||||||
|
|
||||||
if (propertyDatas.containsKey(propertyName)) {
|
if (propertyDatas.containsKey(propertyName)) {
|
||||||
ret |= properties.get(propertyDatas.get(propertyName)).mapToMapFromEntity(session, data,
|
PropertyMapper propertyMapper = properties.get(propertyDatas.get(propertyName));
|
||||||
getAtIndexOrNull(newState, i),
|
Object newObj = getAtIndexOrNull(newState, i);
|
||||||
getAtIndexOrNull(oldState, i));
|
Object oldObj = getAtIndexOrNull(oldState, i);
|
||||||
|
ret |= propertyMapper.mapToMapFromEntity(session, data, newObj, oldObj);
|
||||||
|
propertyMapper.mapModifiedFlagsToMapFromEntity(session, data, newObj, oldObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,18 +113,33 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||||
|
for (PropertyData propertyData : properties.keySet()) {
|
||||||
|
Getter getter;
|
||||||
|
if (newObj != null) {
|
||||||
|
getter = ReflectionTools.getGetter(newObj.getClass(), propertyData);
|
||||||
|
} else if (oldObj != null) {
|
||||||
|
getter = ReflectionTools.getGetter(oldObj.getClass(), propertyData);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.get(propertyData).mapModifiedFlagsToMapFromEntity(session, data,
|
||||||
|
newObj == null ? null : getter.get(newObj),
|
||||||
|
oldObj == null ? null : getter.get(oldObj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||||
AuditReaderImplementor versionsReader, Number revision) {
|
AuditReaderImplementor versionsReader, Number revision) {
|
||||||
for (PropertyMapper mapper : properties.values()) {
|
for (PropertyMapper mapper : properties.values()) {
|
||||||
mapper.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
mapper.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
private Pair<PropertyMapper, String> getMapperAndDelegatePropName(String referencingPropertyName){
|
||||||
PersistentCollection newColl,
|
// Name of the property, to which we will delegate the mapping.
|
||||||
Serializable oldColl,
|
|
||||||
Serializable id) {
|
|
||||||
// Name of the properyt, to which we will delegate the mapping.
|
|
||||||
String delegatePropertyName;
|
String delegatePropertyName;
|
||||||
|
|
||||||
// Checking if the property name doesn't reference a collection in a component - then the name will containa a .
|
// Checking if the property name doesn't reference a collection in a component - then the name will containa a .
|
||||||
|
@ -140,14 +159,30 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
||||||
// If this is not a component, we delegate to the same property.
|
// If this is not a component, we delegate to the same property.
|
||||||
delegatePropertyName = referencingPropertyName;
|
delegatePropertyName = referencingPropertyName;
|
||||||
}
|
}
|
||||||
|
return Pair.make(properties.get(propertyDatas.get(referencingPropertyName)), delegatePropertyName);
|
||||||
|
}
|
||||||
|
|
||||||
PropertyMapper mapper = properties.get(propertyDatas.get(referencingPropertyName));
|
@Override
|
||||||
if (mapper != null) {
|
public void mapModifiedFlagsToMapForCollectionChange(String collectionPropertyName, Map<String, Object> data) {
|
||||||
return mapper.mapCollectionChanges(delegatePropertyName, newColl, oldColl, id);
|
Pair<PropertyMapper, String> pair = getMapperAndDelegatePropName(collectionPropertyName);
|
||||||
} else {
|
PropertyMapper mapper = pair.getFirst();
|
||||||
return null;
|
if (mapper != null) {
|
||||||
}
|
mapper.mapModifiedFlagsToMapForCollectionChange(pair.getSecond(), data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||||
|
PersistentCollection newColl,
|
||||||
|
Serializable oldColl,
|
||||||
|
Serializable id) {
|
||||||
|
Pair<PropertyMapper, String> pair = getMapperAndDelegatePropName(referencingPropertyName);
|
||||||
|
PropertyMapper mapper = pair.getFirst();
|
||||||
|
if (mapper != null) {
|
||||||
|
return mapper.mapCollectionChanges(pair.getSecond(), newColl, oldColl, id);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Map<PropertyData, PropertyMapper> getProperties() {
|
public Map<PropertyData, PropertyMapper> getProperties() {
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public interface PropertyMapper {
|
public interface PropertyMapper {
|
||||||
/**
|
/**
|
||||||
|
@ -68,4 +69,8 @@ public interface PropertyMapper {
|
||||||
List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||||
PersistentCollection newColl,
|
PersistentCollection newColl,
|
||||||
Serializable oldColl, Serializable id);
|
Serializable oldColl, Serializable id);
|
||||||
|
|
||||||
|
void mapModifiedFlagsToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj);
|
||||||
|
void mapModifiedFlagsToMapForCollectionChange(String collectionPropertyName, Map<String, Object> data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.hibernate.property.Setter;
|
||||||
/**
|
/**
|
||||||
* TODO: diff
|
* TODO: diff
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder {
|
public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder {
|
||||||
private PropertyData propertyData;
|
private PropertyData propertyData;
|
||||||
|
@ -65,7 +66,18 @@ public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder
|
||||||
return !Tools.objectsEqual(newObj, oldObj);
|
return !Tools.objectsEqual(newObj, oldObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||||
|
if (propertyData.isUsingModifiedFlag()) {
|
||||||
|
data.put(propertyData.getModifiedFlagPropertyName(), !Tools.objectsEqual(newObj, oldObj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapForCollectionChange(String collectionPropertyName, Map<String, Object> data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||||
AuditReaderImplementor versionsReader, Number revision) {
|
AuditReaderImplementor versionsReader, Number revision) {
|
||||||
if (data == null || obj == null) {
|
if (data == null || obj == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||||
* A mapper which maps from a parent mapper and a "main" one, but adds only to the "main". The "main" mapper
|
* A mapper which maps from a parent mapper and a "main" one, but adds only to the "main". The "main" mapper
|
||||||
* should be the mapper of the subclass.
|
* should be the mapper of the subclass.
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class SubclassPropertyMapper implements ExtendedPropertyMapper {
|
public class SubclassPropertyMapper implements ExtendedPropertyMapper {
|
||||||
private ExtendedPropertyMapper main;
|
private ExtendedPropertyMapper main;
|
||||||
|
@ -60,7 +61,19 @@ public class SubclassPropertyMapper implements ExtendedPropertyMapper {
|
||||||
return parentDiffs || mainDiffs;
|
return parentDiffs || mainDiffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||||
|
parentMapper.mapModifiedFlagsToMapFromEntity(session, data, newObj, oldObj);
|
||||||
|
main.mapModifiedFlagsToMapFromEntity(session, data, newObj, oldObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapForCollectionChange(String collectionPropertyName, Map<String, Object> data) {
|
||||||
|
parentMapper.mapModifiedFlagsToMapForCollectionChange(collectionPropertyName, data);
|
||||||
|
main.mapModifiedFlagsToMapForCollectionChange(collectionPropertyName, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
|
||||||
parentMapper.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
parentMapper.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
||||||
main.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
main.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
|
import org.hibernate.envers.entities.PropertyData;
|
||||||
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
||||||
import org.hibernate.envers.entities.mapper.PropertyMapper;
|
import org.hibernate.envers.entities.mapper.PropertyMapper;
|
||||||
import org.hibernate.envers.entities.mapper.relation.lazy.initializor.Initializor;
|
import org.hibernate.envers.entities.mapper.relation.lazy.initializor.Initializor;
|
||||||
|
@ -47,6 +48,7 @@ import org.hibernate.property.Setter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
|
public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
|
||||||
protected final CommonCollectionMapperData commonCollectionMapperData;
|
protected final CommonCollectionMapperData commonCollectionMapperData;
|
||||||
|
@ -133,7 +135,39 @@ public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Initializor<T> getInitializor(AuditConfiguration verCfg,
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||||
|
PropertyData propertyData = commonCollectionMapperData.getCollectionReferencingPropertyData();
|
||||||
|
if (propertyData.isUsingModifiedFlag()) {
|
||||||
|
if(isFromNullToEmptyOrFromEmptyToNull((PersistentCollection) newObj, (Serializable) oldObj)){
|
||||||
|
data.put(propertyData.getModifiedFlagPropertyName(), true);
|
||||||
|
} else {
|
||||||
|
List<PersistentCollectionChangeData> changes = mapCollectionChanges(
|
||||||
|
commonCollectionMapperData.getCollectionReferencingPropertyData().getName(),
|
||||||
|
(PersistentCollection) newObj, (Serializable) oldObj, null);
|
||||||
|
data.put(propertyData.getModifiedFlagPropertyName(), !changes.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFromNullToEmptyOrFromEmptyToNull(PersistentCollection newColl, Serializable oldColl) {
|
||||||
|
// Comparing new and old collection content.
|
||||||
|
Collection newCollection = getNewCollectionContent(newColl);
|
||||||
|
Collection oldCollection = getOldCollectionContent(oldColl);
|
||||||
|
|
||||||
|
return oldCollection == null && newCollection != null && newCollection.isEmpty()
|
||||||
|
|| newCollection == null && oldCollection != null && oldCollection.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapForCollectionChange(String collectionPropertyName, Map<String, Object> data) {
|
||||||
|
PropertyData propertyData = commonCollectionMapperData.getCollectionReferencingPropertyData();
|
||||||
|
if (propertyData.isUsingModifiedFlag()) {
|
||||||
|
data.put(propertyData.getModifiedFlagPropertyName(), propertyData.getName().equals(collectionPropertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Initializor<T> getInitializor(AuditConfiguration verCfg,
|
||||||
AuditReaderImplementor versionsReader, Object primaryKey,
|
AuditReaderImplementor versionsReader, Object primaryKey,
|
||||||
Number revision);
|
Number revision);
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.hibernate.property.Setter;
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Hern<EFBFBD>n Chanfreau
|
* @author Hern<EFBFBD>n Chanfreau
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class OneToOneNotOwningMapper implements PropertyMapper {
|
public class OneToOneNotOwningMapper implements PropertyMapper {
|
||||||
private String owningReferencePropertyName;
|
private String owningReferencePropertyName;
|
||||||
|
@ -61,7 +62,18 @@ public class OneToOneNotOwningMapper implements PropertyMapper {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapForCollectionChange(String collectionPropertyName, Map<String, Object> data) {
|
||||||
|
if (propertyData.isUsingModifiedFlag()) {
|
||||||
|
data.put(propertyData.getModifiedFlagPropertyName(), collectionPropertyName.equals(propertyData.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.hibernate.property.Setter;
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Hern<EFBFBD>n Chanfreau
|
* @author Hern<EFBFBD>n Chanfreau
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class ToOneIdMapper implements PropertyMapper {
|
public class ToOneIdMapper implements PropertyMapper {
|
||||||
private final IdMapper delegate;
|
private final IdMapper delegate;
|
||||||
|
@ -71,11 +72,29 @@ public class ToOneIdMapper implements PropertyMapper {
|
||||||
data.put(entry.getKey(), entry.getValue());
|
data.put(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection SimplifiableConditionalExpression
|
return checkModified(session, newObj, oldObj);
|
||||||
return nonInsertableFake ? false : !Tools.entitiesEqual(session, referencedEntityName, newObj, oldObj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||||
|
if (propertyData.isUsingModifiedFlag()) {
|
||||||
|
data.put(propertyData.getModifiedFlagPropertyName(), checkModified(session, newObj, oldObj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mapModifiedFlagsToMapForCollectionChange(String collectionPropertyName, Map<String, Object> data) {
|
||||||
|
if (propertyData.isUsingModifiedFlag()) {
|
||||||
|
data.put(propertyData.getModifiedFlagPropertyName(), collectionPropertyName.equals(propertyData.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkModified(SessionImplementor session, Object newObj, Object oldObj) {
|
||||||
|
//noinspection SimplifiableConditionalExpression
|
||||||
|
return nonInsertableFake ? false : !Tools.entitiesEqual(session, referencedEntityName, newObj, oldObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||||
AuditReaderImplementor versionsReader, Number revision) {
|
AuditReaderImplementor versionsReader, Number revision) {
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.envers.event;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.spi.CollectionEntry;
|
import org.hibernate.engine.spi.CollectionEntry;
|
||||||
|
@ -48,6 +49,7 @@ import org.hibernate.persister.collection.AbstractCollectionPersister;
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Hern<EFBFBD>n Chanfreau
|
* @author Hern<EFBFBD>n Chanfreau
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public abstract class BaseEnversCollectionEventListener extends BaseEnversEventListener {
|
public abstract class BaseEnversCollectionEventListener extends BaseEnversEventListener {
|
||||||
protected BaseEnversCollectionEventListener(AuditConfiguration enversConfiguration) {
|
protected BaseEnversCollectionEventListener(AuditConfiguration enversConfiguration) {
|
||||||
|
@ -106,6 +108,7 @@ public abstract class BaseEnversCollectionEventListener extends BaseEnversEventL
|
||||||
new CollectionChangeWorkUnit(
|
new CollectionChangeWorkUnit(
|
||||||
event.getSession(),
|
event.getSession(),
|
||||||
event.getAffectedOwnerEntityName(),
|
event.getAffectedOwnerEntityName(),
|
||||||
|
referencingPropertyName,
|
||||||
getAuditConfiguration(),
|
getAuditConfiguration(),
|
||||||
event.getAffectedOwnerIdOrNull(),
|
event.getAffectedOwnerIdOrNull(),
|
||||||
event.getAffectedOwnerOrNull()
|
event.getAffectedOwnerOrNull()
|
||||||
|
@ -174,6 +177,7 @@ public abstract class BaseEnversCollectionEventListener extends BaseEnversEventL
|
||||||
AuditWorkUnit nestedWorkUnit = new CollectionChangeWorkUnit(
|
AuditWorkUnit nestedWorkUnit = new CollectionChangeWorkUnit(
|
||||||
event.getSession(),
|
event.getSession(),
|
||||||
realRelatedEntityName,
|
realRelatedEntityName,
|
||||||
|
rd.getMappedByPropertyName(),
|
||||||
getAuditConfiguration(),
|
getAuditConfiguration(),
|
||||||
relatedId,
|
relatedId,
|
||||||
relatedObj
|
relatedObj
|
||||||
|
@ -200,6 +204,7 @@ public abstract class BaseEnversCollectionEventListener extends BaseEnversEventL
|
||||||
new CollectionChangeWorkUnit(
|
new CollectionChangeWorkUnit(
|
||||||
event.getSession(),
|
event.getSession(),
|
||||||
collectionEntityName,
|
collectionEntityName,
|
||||||
|
referencingPropertyName,
|
||||||
getAuditConfiguration(),
|
getAuditConfiguration(),
|
||||||
event.getAffectedOwnerIdOrNull(),
|
event.getAffectedOwnerIdOrNull(),
|
||||||
event.getAffectedOwnerOrNull()
|
event.getAffectedOwnerOrNull()
|
||||||
|
@ -224,6 +229,10 @@ public abstract class BaseEnversCollectionEventListener extends BaseEnversEventL
|
||||||
String relatedEntityName = rd.getToEntityName();
|
String relatedEntityName = rd.getToEntityName();
|
||||||
IdMapper relatedIdMapper = getAuditConfiguration().getEntCfg().get( relatedEntityName ).getIdMapper();
|
IdMapper relatedIdMapper = getAuditConfiguration().getEntCfg().get( relatedEntityName ).getIdMapper();
|
||||||
|
|
||||||
|
Set<String> toPropertyNames = getAuditConfiguration().getEntCfg()
|
||||||
|
.getToPropertyNames(event.getAffectedOwnerEntityName(), rd.getFromPropertyName(), relatedEntityName);
|
||||||
|
String toPropertyName = toPropertyNames.iterator().next();
|
||||||
|
|
||||||
for ( PersistentCollectionChangeData changeData : workUnit.getCollectionChanges() ) {
|
for ( PersistentCollectionChangeData changeData : workUnit.getCollectionChanges() ) {
|
||||||
Object relatedObj = changeData.getChangedElement();
|
Object relatedObj = changeData.getChangedElement();
|
||||||
Serializable relatedId = (Serializable) relatedIdMapper.mapToIdFromEntity( relatedObj );
|
Serializable relatedId = (Serializable) relatedIdMapper.mapToIdFromEntity( relatedObj );
|
||||||
|
@ -232,6 +241,7 @@ public abstract class BaseEnversCollectionEventListener extends BaseEnversEventL
|
||||||
new CollectionChangeWorkUnit(
|
new CollectionChangeWorkUnit(
|
||||||
event.getSession(),
|
event.getSession(),
|
||||||
event.getSession().bestGuessEntityName(relatedObj),
|
event.getSession().bestGuessEntityName(relatedObj),
|
||||||
|
toPropertyName,
|
||||||
getAuditConfiguration(),
|
getAuditConfiguration(),
|
||||||
relatedId,
|
relatedId,
|
||||||
relatedObj
|
relatedObj
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
package org.hibernate.envers.event;
|
package org.hibernate.envers.event;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
|
@ -42,6 +43,7 @@ import org.hibernate.proxy.HibernateProxy;
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Hern<EFBFBD>n Chanfreau
|
* @author Hern<EFBFBD>n Chanfreau
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public abstract class BaseEnversEventListener implements EnversListener {
|
public abstract class BaseEnversEventListener implements EnversListener {
|
||||||
private AuditConfiguration enversConfiguration;
|
private AuditConfiguration enversConfiguration;
|
||||||
|
@ -85,49 +87,41 @@ public abstract class BaseEnversEventListener implements EnversListener {
|
||||||
// We have to generate changes both in the old collection (size decreses) and new collection
|
// We have to generate changes both in the old collection (size decreses) and new collection
|
||||||
// (size increases).
|
// (size increases).
|
||||||
if (newValue != null) {
|
if (newValue != null) {
|
||||||
// relDesc.getToEntityName() doesn't always return the entity name of the value - in case
|
addCollectionChangeWorkUnit(auditProcess, session, entityName, relDesc, newValue);
|
||||||
// of subclasses, this will be root class, no the actual class. So it can't be used here.
|
|
||||||
String toEntityName;
|
|
||||||
Serializable id;
|
|
||||||
|
|
||||||
if (newValue instanceof HibernateProxy ) {
|
|
||||||
HibernateProxy hibernateProxy = (HibernateProxy) newValue;
|
|
||||||
toEntityName = session.bestGuessEntityName(newValue);
|
|
||||||
id = hibernateProxy.getHibernateLazyInitializer().getIdentifier();
|
|
||||||
// We've got to initialize the object from the proxy to later read its state.
|
|
||||||
newValue = Tools.getTargetFromProxy(session.getFactory(), hibernateProxy);
|
|
||||||
} else {
|
|
||||||
toEntityName = session.guessEntityName(newValue);
|
|
||||||
|
|
||||||
IdMapper idMapper = enversConfiguration.getEntCfg().get(toEntityName).getIdMapper();
|
|
||||||
id = (Serializable) idMapper.mapToIdFromEntity(newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
auditProcess.addWorkUnit(new CollectionChangeWorkUnit(session, toEntityName, enversConfiguration, id, newValue));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldValue != null) {
|
if (oldValue != null) {
|
||||||
String toEntityName;
|
addCollectionChangeWorkUnit(auditProcess, session, entityName, relDesc, oldValue);
|
||||||
Serializable id;
|
|
||||||
|
|
||||||
if(oldValue instanceof HibernateProxy) {
|
|
||||||
HibernateProxy hibernateProxy = (HibernateProxy) oldValue;
|
|
||||||
toEntityName = session.bestGuessEntityName(oldValue);
|
|
||||||
id = hibernateProxy.getHibernateLazyInitializer().getIdentifier();
|
|
||||||
// We've got to initialize the object as we'll read it's state anyway.
|
|
||||||
oldValue = Tools.getTargetFromProxy(session.getFactory(), hibernateProxy);
|
|
||||||
} else {
|
|
||||||
toEntityName = session.guessEntityName(oldValue);
|
|
||||||
|
|
||||||
IdMapper idMapper = enversConfiguration.getEntCfg().get(toEntityName).getIdMapper();
|
|
||||||
id = (Serializable) idMapper.mapToIdFromEntity(oldValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
auditProcess.addWorkUnit(new CollectionChangeWorkUnit(session, toEntityName, enversConfiguration, id, oldValue));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addCollectionChangeWorkUnit(AuditProcess auditProcess, SessionImplementor session,
|
||||||
|
String fromEntityName, RelationDescription relDesc, Object value) {
|
||||||
|
// relDesc.getToEntityName() doesn't always return the entity name of the value - in case
|
||||||
|
// of subclasses, this will be root class, no the actual class. So it can't be used here.
|
||||||
|
String toEntityName;
|
||||||
|
Serializable id;
|
||||||
|
|
||||||
|
if (value instanceof HibernateProxy) {
|
||||||
|
HibernateProxy hibernateProxy = (HibernateProxy) value;
|
||||||
|
toEntityName = session.bestGuessEntityName(value);
|
||||||
|
id = hibernateProxy.getHibernateLazyInitializer().getIdentifier();
|
||||||
|
} else {
|
||||||
|
toEntityName = session.guessEntityName(value);
|
||||||
|
|
||||||
|
IdMapper idMapper = enversConfiguration.getEntCfg().get(toEntityName).getIdMapper();
|
||||||
|
id = (Serializable) idMapper.mapToIdFromEntity(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> toPropertyNames = enversConfiguration.getEntCfg()
|
||||||
|
.getToPropertyNames(fromEntityName, relDesc.getFromPropertyName(), toEntityName);
|
||||||
|
String toPropertyName = toPropertyNames.iterator().next();
|
||||||
|
|
||||||
|
auditProcess.addWorkUnit(new CollectionChangeWorkUnit(session, toEntityName,
|
||||||
|
toPropertyName, enversConfiguration, id, value));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,14 @@ import org.hibernate.envers.query.order.AuditOrder;
|
||||||
import org.hibernate.envers.query.order.PropertyAuditOrder;
|
import org.hibernate.envers.query.order.PropertyAuditOrder;
|
||||||
import org.hibernate.envers.query.projection.AuditProjection;
|
import org.hibernate.envers.query.projection.AuditProjection;
|
||||||
import org.hibernate.envers.query.projection.PropertyAuditProjection;
|
import org.hibernate.envers.query.projection.PropertyAuditProjection;
|
||||||
|
import org.hibernate.envers.query.property.ModifiedFlagPropertyName;
|
||||||
import org.hibernate.envers.query.property.PropertyNameGetter;
|
import org.hibernate.envers.query.property.PropertyNameGetter;
|
||||||
import org.hibernate.envers.tools.Triple;
|
import org.hibernate.envers.tools.Triple;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create restrictions, projections and specify order for a property of an audited entity.
|
* Create restrictions, projections and specify order for a property of an audited entity.
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"JavaDoc"})
|
@SuppressWarnings({"JavaDoc"})
|
||||||
public class AuditProperty<T> implements AuditProjection {
|
public class AuditProperty<T> implements AuditProjection {
|
||||||
|
@ -46,7 +48,15 @@ public class AuditProperty<T> implements AuditProjection {
|
||||||
this.propertyNameGetter = propertyNameGetter;
|
this.propertyNameGetter = propertyNameGetter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public AuditCriterion hasChanged() {
|
||||||
|
return new SimpleAuditExpression(new ModifiedFlagPropertyName(propertyNameGetter), true, "=");
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuditCriterion hasNotChanged() {
|
||||||
|
return new SimpleAuditExpression(new ModifiedFlagPropertyName(propertyNameGetter), false, "=");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* Apply an "equal" constraint
|
* Apply an "equal" constraint
|
||||||
*/
|
*/
|
||||||
public AuditCriterion eq(T value) {
|
public AuditCriterion eq(T value) {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.envers.query.property;
|
||||||
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
|
import org.hibernate.envers.configuration.metadata.MetadataTools;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PropertyNameGetter for modified flags
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class ModifiedFlagPropertyName implements PropertyNameGetter {
|
||||||
|
private final PropertyNameGetter propertyNameGetter;
|
||||||
|
|
||||||
|
public ModifiedFlagPropertyName(PropertyNameGetter propertyNameGetter) {
|
||||||
|
this.propertyNameGetter = propertyNameGetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(AuditConfiguration auditCfg) {
|
||||||
|
return MetadataTools.getModifiedFlagPropertyName(
|
||||||
|
propertyNameGetter.get(auditCfg),
|
||||||
|
auditCfg.getGlobalCfg().getModifiedFlagSuffix());
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,8 +85,9 @@ public class AddWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuditWorkUnit merge(CollectionChangeWorkUnit second) {
|
public AuditWorkUnit merge(CollectionChangeWorkUnit second) {
|
||||||
return this;
|
second.mergeCollectionModifiedData(data);
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public AuditWorkUnit merge(FakeBidirectionalRelationWorkUnit second) {
|
public AuditWorkUnit merge(FakeBidirectionalRelationWorkUnit second) {
|
||||||
return FakeBidirectionalRelationWorkUnit.merge(second, this, second.getNestedWorkUnit());
|
return FakeBidirectionalRelationWorkUnit.merge(second, this, second.getNestedWorkUnit());
|
||||||
|
|
|
@ -25,22 +25,28 @@ package org.hibernate.envers.synchronization.work;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
|
import org.hibernate.envers.tools.Tools;
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
*/
|
*/
|
||||||
public class CollectionChangeWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit {
|
public class CollectionChangeWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit {
|
||||||
private final Object entity;
|
private Object entity;
|
||||||
|
private final String collectionPropertyName;
|
||||||
|
private final Map<String, Object> data = new HashMap<String, Object>();
|
||||||
|
|
||||||
public CollectionChangeWorkUnit(SessionImplementor session, String entityName, AuditConfiguration verCfg,
|
public CollectionChangeWorkUnit(SessionImplementor session, String entityName, String collectionPropertyName,
|
||||||
Serializable id, Object entity) {
|
AuditConfiguration verCfg, Serializable id, Object entity) {
|
||||||
super(session, entityName, verCfg, id, RevisionType.MOD);
|
super(session, entityName, verCfg, id, RevisionType.MOD);
|
||||||
|
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
|
this.collectionPropertyName = collectionPropertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsWork() {
|
public boolean containsWork() {
|
||||||
|
@ -48,16 +54,32 @@ public class CollectionChangeWorkUnit extends AbstractAuditWorkUnit implements A
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> generateData(Object revisionData) {
|
public Map<String, Object> generateData(Object revisionData) {
|
||||||
Map<String, Object> data = new HashMap<String, Object>();
|
|
||||||
fillDataWithId(data, revisionData);
|
fillDataWithId(data, revisionData);
|
||||||
|
resolveProxyIfNeeded();
|
||||||
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().mapToMapFromEntity(sessionImplementor,
|
Map<String, Object> preGenerateData = new HashMap<String, Object>(data);
|
||||||
data, entity, null);
|
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper()
|
||||||
|
.mapToMapFromEntity(sessionImplementor, data, entity, null);
|
||||||
|
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper()
|
||||||
|
.mapModifiedFlagsToMapFromEntity(sessionImplementor, data, entity, entity);
|
||||||
|
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper()
|
||||||
|
.mapModifiedFlagsToMapForCollectionChange(collectionPropertyName, data);
|
||||||
|
data.putAll(preGenerateData);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuditWorkUnit merge(AddWorkUnit second) {
|
private void resolveProxyIfNeeded() {
|
||||||
|
if (entity instanceof HibernateProxy) {
|
||||||
|
Tools.getTargetFromProxy(sessionImplementor.getFactory(), (HibernateProxy) entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mergeCollectionModifiedData(Map<String, Object> data) {
|
||||||
|
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper()
|
||||||
|
.mapModifiedFlagsToMapForCollectionChange(
|
||||||
|
collectionPropertyName, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuditWorkUnit merge(AddWorkUnit second) {
|
||||||
return second;
|
return second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +92,7 @@ public class CollectionChangeWorkUnit extends AbstractAuditWorkUnit implements A
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuditWorkUnit merge(CollectionChangeWorkUnit second) {
|
public AuditWorkUnit merge(CollectionChangeWorkUnit second) {
|
||||||
|
second.mergeCollectionModifiedData(data);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,9 @@ public class DelWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
|
||||||
if (verCfg.getGlobalCfg().isStoreDataAtDelete()) {
|
if (verCfg.getGlobalCfg().isStoreDataAtDelete()) {
|
||||||
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(sessionImplementor, data,
|
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(sessionImplementor, data,
|
||||||
propertyNames, state, state);
|
propertyNames, state, state);
|
||||||
|
} else {
|
||||||
|
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(sessionImplementor, data,
|
||||||
|
propertyNames, null, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
|
@ -153,11 +153,15 @@ public class FakeBidirectionalRelationWorkUnit extends AbstractAuditWorkUnit imp
|
||||||
// new owner will in fact be null.
|
// new owner will in fact be null.
|
||||||
rd.getFakeBidirectionalRelationMapper().mapToMapFromEntity(sessionImplementor, data,
|
rd.getFakeBidirectionalRelationMapper().mapToMapFromEntity(sessionImplementor, data,
|
||||||
revisionType == RevisionType.DEL ? null : owningEntity, null);
|
revisionType == RevisionType.DEL ? null : owningEntity, null);
|
||||||
|
rd.getFakeBidirectionalRelationMapper().mapModifiedFlagsToMapFromEntity(sessionImplementor, data,
|
||||||
|
revisionType == RevisionType.DEL ? null : owningEntity, null);
|
||||||
|
|
||||||
// Also mapping the index, if the collection is indexed.
|
// Also mapping the index, if the collection is indexed.
|
||||||
if (rd.getFakeBidirectionalRelationIndexMapper() != null) {
|
if (rd.getFakeBidirectionalRelationIndexMapper() != null) {
|
||||||
rd.getFakeBidirectionalRelationIndexMapper().mapToMapFromEntity(sessionImplementor, data,
|
rd.getFakeBidirectionalRelationIndexMapper().mapToMapFromEntity(sessionImplementor, data,
|
||||||
revisionType == RevisionType.DEL ? null : index, null);
|
revisionType == RevisionType.DEL ? null : index, null);
|
||||||
|
rd.getFakeBidirectionalRelationIndexMapper().mapModifiedFlagsToMapFromEntity(sessionImplementor, data,
|
||||||
|
revisionType == RevisionType.DEL ? null : index, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ public abstract class AbstractOneSessionTest extends AbstractEnversTest {
|
||||||
if (auditStrategy != null && !"".equals(auditStrategy)) {
|
if (auditStrategy != null && !"".equals(auditStrategy)) {
|
||||||
config.setProperty("org.hibernate.envers.audit_strategy", auditStrategy);
|
config.setProperty("org.hibernate.envers.audit_strategy", auditStrategy);
|
||||||
}
|
}
|
||||||
|
addProperties(config);
|
||||||
|
|
||||||
this.initMappings();
|
this.initMappings();
|
||||||
|
|
||||||
|
@ -50,6 +51,8 @@ public abstract class AbstractOneSessionTest extends AbstractEnversTest {
|
||||||
|
|
||||||
protected abstract void initMappings() throws MappingException, URISyntaxException ;
|
protected abstract void initMappings() throws MappingException, URISyntaxException ;
|
||||||
|
|
||||||
|
protected void addProperties(Configuration configuration) {}
|
||||||
|
|
||||||
protected String getHibernateConfigurationFileName(){
|
protected String getHibernateConfigurationFileName(){
|
||||||
return "hibernate.test.session-cfg.xml";
|
return "hibernate.test.session-cfg.xml";
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
|
import org.hibernate.envers.query.AuditEntity;
|
||||||
|
import org.hibernate.envers.query.AuditQuery;
|
||||||
|
import org.hibernate.envers.test.AbstractEntityTest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base test for modified flags feature
|
||||||
|
*
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public abstract class AbstractModifiedFlagsEntityTest extends AbstractEntityTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addConfigurationProperties(Properties configuration) {
|
||||||
|
super.addConfigurationProperties(configuration);
|
||||||
|
if (forceModifiedFlags()) {
|
||||||
|
configuration.setProperty(
|
||||||
|
GlobalConfiguration.GLOBAL_WITH_MODIFIED_FLAG_PROPERTY, "true");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean forceModifiedFlags() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List queryForPropertyHasChanged(Class<?> clazz, Object id,
|
||||||
|
String... propertyNames) {
|
||||||
|
AuditQuery query = createForRevisionsQuery(clazz, id, false);
|
||||||
|
addHasChangedProperties(query, propertyNames);
|
||||||
|
return query.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List queryForPropertyHasChangedWithDeleted(Class<?> clazz, Object id,
|
||||||
|
String... propertyNames) {
|
||||||
|
AuditQuery query = createForRevisionsQuery(clazz, id, true);
|
||||||
|
addHasChangedProperties(query, propertyNames);
|
||||||
|
return query.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List queryForPropertyHasNotChanged(Class<?> clazz, Object id,
|
||||||
|
String... propertyNames) {
|
||||||
|
AuditQuery query = createForRevisionsQuery(clazz, id, false);
|
||||||
|
addHasNotChangedProperties(query, propertyNames);
|
||||||
|
return query.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List queryForPropertyHasNotChangedWithDeleted(Class<?> clazz, Object id,
|
||||||
|
String... propertyNames) {
|
||||||
|
AuditQuery query = createForRevisionsQuery(clazz, id, true);
|
||||||
|
addHasNotChangedProperties(query, propertyNames);
|
||||||
|
return query.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addHasChangedProperties(AuditQuery query,
|
||||||
|
String[] propertyNames) {
|
||||||
|
for (String propertyName : propertyNames) {
|
||||||
|
query.add(AuditEntity.property(propertyName).hasChanged());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addHasNotChangedProperties(AuditQuery query,
|
||||||
|
String[] propertyNames) {
|
||||||
|
for (String propertyName : propertyNames) {
|
||||||
|
query.add(AuditEntity.property(propertyName).hasNotChanged());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuditQuery createForRevisionsQuery(Class<?> clazz, Object id, boolean withDeleted) {
|
||||||
|
return getAuditReader().createQuery()
|
||||||
|
.forRevisionsOfEntity(clazz, false, withDeleted)
|
||||||
|
.add(AuditEntity.id().eq(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
|
import org.hibernate.envers.test.AbstractOneSessionTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base test for modified flags feature
|
||||||
|
*
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public abstract class AbstractModifiedFlagsOneSessionTest extends
|
||||||
|
AbstractOneSessionTest {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addProperties(Configuration configuration) {
|
||||||
|
super.addProperties(configuration);
|
||||||
|
if (forceModifiedFlags()) {
|
||||||
|
configuration.setProperty(
|
||||||
|
GlobalConfiguration.GLOBAL_WITH_MODIFIED_FLAG_PROPERTY, "true");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean forceModifiedFlags() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.query.AuditEntity;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.integration.auditReader.AuditedTestEntity;
|
||||||
|
import org.hibernate.envers.test.integration.auditReader.NotAuditedTestEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test which checks the correct behavior of AuditReader.isEntityClassAudited(Class entityClass).
|
||||||
|
*
|
||||||
|
* @author Hernan Chanfreau
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedAPITest extends AbstractModifiedFlagsEntityTest {
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(AuditedTestEntity.class);
|
||||||
|
cfg.addAnnotatedClass(NotAuditedTestEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
AuditedTestEntity ent1 = new AuditedTestEntity(1, "str1");
|
||||||
|
NotAuditedTestEntity ent2 = new NotAuditedTestEntity(1, "str1");
|
||||||
|
|
||||||
|
em.persist(ent1);
|
||||||
|
em.persist(ent2);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ent1 = em.find(AuditedTestEntity.class, 1);
|
||||||
|
ent2 = em.find(NotAuditedTestEntity.class, 1);
|
||||||
|
ent1.setStr1("str2");
|
||||||
|
ent2.setStr1("str2");
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedHasNotChangedCriteria() throws Exception {
|
||||||
|
List list = getAuditReader().createQuery().forRevisionsOfEntity(AuditedTestEntity.class, true, true)
|
||||||
|
.add(AuditEntity.property("str1").hasChanged()).getResultList();
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals("str1", ((AuditedTestEntity) list.get(0)).getStr1());
|
||||||
|
assertEquals("str2", ((AuditedTestEntity) list.get(1)).getStr1());
|
||||||
|
|
||||||
|
list = getAuditReader().createQuery().forRevisionsOfEntity(AuditedTestEntity.class, true, true)
|
||||||
|
.add(AuditEntity.property("str1").hasNotChanged()).getResultList();
|
||||||
|
assertTrue(list.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.envers.query.AuditEntity;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.integration.entityNames.manyToManyAudited.Car;
|
||||||
|
import org.hibernate.envers.test.integration.entityNames.manyToManyAudited.Person;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Hernán Chanfreau
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class HasChangedAuditedManyToManyTest extends AbstractModifiedFlagsOneSessionTest{
|
||||||
|
|
||||||
|
private long id_car1;
|
||||||
|
|
||||||
|
private long id_pers1;
|
||||||
|
private long id_pers2;
|
||||||
|
|
||||||
|
protected void initMappings() throws MappingException, URISyntaxException {
|
||||||
|
URL url = Thread.currentThread().getContextClassLoader().getResource("mappings/entityNames/manyToManyAudited/mappings.hbm.xml");
|
||||||
|
config.addFile(new File(url.toURI()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
|
||||||
|
initializeSession();
|
||||||
|
|
||||||
|
Person pers1 = new Person("Hernan", 28);
|
||||||
|
Person pers2 = new Person("Leandro", 29);
|
||||||
|
Person pers3 = new Person("Barba", 32);
|
||||||
|
Person pers4 = new Person("Camomo", 15);
|
||||||
|
|
||||||
|
//REV 1
|
||||||
|
getSession().getTransaction().begin();
|
||||||
|
List<Person > owners = new ArrayList<Person>();
|
||||||
|
owners.add(pers1);
|
||||||
|
owners.add(pers2);
|
||||||
|
owners.add(pers3);
|
||||||
|
Car car1 = new Car(5, owners);
|
||||||
|
|
||||||
|
getSession().persist(car1);
|
||||||
|
getSession().getTransaction().commit();
|
||||||
|
id_pers1 = pers1.getId();
|
||||||
|
id_car1 = car1.getId();
|
||||||
|
id_pers2 = pers2.getId();
|
||||||
|
|
||||||
|
owners = new ArrayList<Person>();
|
||||||
|
owners.add(pers2);
|
||||||
|
owners.add(pers3);
|
||||||
|
owners.add(pers4);
|
||||||
|
Car car2 = new Car(27, owners);
|
||||||
|
//REV 2
|
||||||
|
getSession().getTransaction().begin();
|
||||||
|
Person person1 = (Person)getSession().get("Personaje", id_pers1);
|
||||||
|
person1.setName("Hernan David");
|
||||||
|
person1.setAge(40);
|
||||||
|
getSession().persist(car1);
|
||||||
|
getSession().persist(car2);
|
||||||
|
getSession().getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedPerson1() throws Exception {
|
||||||
|
List list = getAuditReader().createQuery().forRevisionsOfEntity(Person.class, "Personaje", false, false)
|
||||||
|
.add(AuditEntity.id().eq(id_pers1))
|
||||||
|
.add(AuditEntity.property("cars").hasChanged())
|
||||||
|
.getResultList();
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = getAuditReader().createQuery().forRevisionsOfEntity(Person.class, "Personaje", false, false)
|
||||||
|
.add(AuditEntity.id().eq(id_pers1))
|
||||||
|
.add(AuditEntity.property("cars").hasNotChanged())
|
||||||
|
.getResultList();
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(2), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedPerson2() throws Exception {
|
||||||
|
List list = getAuditReader().createQuery().forRevisionsOfEntity(Person.class, "Personaje", false, false)
|
||||||
|
.add(AuditEntity.id().eq(id_pers2))
|
||||||
|
.add(AuditEntity.property("cars").hasChanged())
|
||||||
|
.getResultList();
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = getAuditReader().createQuery().forRevisionsOfEntity(Person.class, "Personaje", false, false)
|
||||||
|
.add(AuditEntity.id().eq(id_pers2))
|
||||||
|
.add(AuditEntity.property("cars").hasNotChanged())
|
||||||
|
.getResultList();
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedCar1() throws Exception {
|
||||||
|
List list = getAuditReader().createQuery().forRevisionsOfEntity(Car.class, false, false)
|
||||||
|
.add(AuditEntity.id().eq(id_car1))
|
||||||
|
.add(AuditEntity.property("owners").hasChanged())
|
||||||
|
.getResultList();
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = getAuditReader().createQuery().forRevisionsOfEntity(Car.class, false, false)
|
||||||
|
.add(AuditEntity.id().eq(id_car1))
|
||||||
|
.add(AuditEntity.property("owners").hasNotChanged())
|
||||||
|
.getResultList();
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.integration.onetoone.bidirectional.BiRefEdEntity;
|
||||||
|
import org.hibernate.envers.test.integration.onetoone.bidirectional.BiRefIngEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedBidirectional2 extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer ed1_id;
|
||||||
|
private Integer ed2_id;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(BiRefEdEntity.class);
|
||||||
|
cfg.addAnnotatedClass(BiRefIngEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
BiRefEdEntity ed1 = new BiRefEdEntity(1, "data_ed_1");
|
||||||
|
BiRefEdEntity ed2 = new BiRefEdEntity(2, "data_ed_2");
|
||||||
|
|
||||||
|
BiRefIngEntity ing1 = new BiRefIngEntity(3, "data_ing_1");
|
||||||
|
BiRefIngEntity ing2 = new BiRefIngEntity(4, "data_ing_2");
|
||||||
|
|
||||||
|
// Revision 1
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
em.persist(ed1);
|
||||||
|
em.persist(ed2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ed1 = em.find(BiRefEdEntity.class, ed1.getId());
|
||||||
|
|
||||||
|
ing1.setReference(ed1);
|
||||||
|
|
||||||
|
em.persist(ing1);
|
||||||
|
em.persist(ing2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 3
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ed1 = em.find(BiRefEdEntity.class, ed1.getId());
|
||||||
|
ing1 = em.find(BiRefIngEntity.class, ing1.getId());
|
||||||
|
ing2 = em.find(BiRefIngEntity.class, ing2.getId());
|
||||||
|
|
||||||
|
ing1.setReference(null);
|
||||||
|
ing2.setReference(ed1);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 4
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ed2 = em.find(BiRefEdEntity.class, ed2.getId());
|
||||||
|
ing1 = em.find(BiRefIngEntity.class, ing1.getId());
|
||||||
|
ing2 = em.find(BiRefIngEntity.class, ing2.getId());
|
||||||
|
|
||||||
|
ing1.setReference(ed2);
|
||||||
|
ing2.setReference(null);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
ed1_id = ed1.getId();
|
||||||
|
ed2_id = ed2.getId();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(BiRefEdEntity.class, ed1_id,
|
||||||
|
"referencing");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(2, 3, 4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(BiRefEdEntity.class, ed2_id,
|
||||||
|
"referencing");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(4), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.integration.inheritance.joined.ChildEntity;
|
||||||
|
import org.hibernate.envers.test.integration.inheritance.joined.ParentEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedChildAuditing extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer id1;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(ChildEntity.class);
|
||||||
|
cfg.addAnnotatedClass(ParentEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
id1 = 1;
|
||||||
|
|
||||||
|
// Rev 1
|
||||||
|
em.getTransaction().begin();
|
||||||
|
ChildEntity ce = new ChildEntity(id1, "x", 1l);
|
||||||
|
em.persist(ce);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Rev 2
|
||||||
|
em.getTransaction().begin();
|
||||||
|
ce = em.find(ChildEntity.class, id1);
|
||||||
|
ce.setData("y");
|
||||||
|
ce.setNumber(2l);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChildHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(ChildEntity.class, id1, "data");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(ChildEntity.class, id1, "number");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(ChildEntity.class, id1, "data");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(ChildEntity.class, id1, "number");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParentHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(ParentEntity.class, id1, "data");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(ParentEntity.class, id1, "data");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.integration.inheritance.joined.childrelation.ChildIngEntity;
|
||||||
|
import org.hibernate.envers.test.integration.inheritance.joined.childrelation.ParentNotIngEntity;
|
||||||
|
import org.hibernate.envers.test.integration.inheritance.joined.childrelation.ReferencedEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedChildReferencing extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer re_id1;
|
||||||
|
private Integer re_id2;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(ChildIngEntity.class);
|
||||||
|
cfg.addAnnotatedClass(ParentNotIngEntity.class);
|
||||||
|
cfg.addAnnotatedClass(ReferencedEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
re_id1 = 1;
|
||||||
|
re_id2 = 10;
|
||||||
|
Integer c_id = 100;
|
||||||
|
|
||||||
|
// Rev 1
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ReferencedEntity re1 = new ReferencedEntity(re_id1);
|
||||||
|
em.persist(re1);
|
||||||
|
|
||||||
|
ReferencedEntity re2 = new ReferencedEntity(re_id2);
|
||||||
|
em.persist(re2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Rev 2
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
re1 = em.find(ReferencedEntity.class, re_id1);
|
||||||
|
|
||||||
|
ChildIngEntity cie = new ChildIngEntity(c_id, "y", 1l);
|
||||||
|
cie.setReferenced(re1);
|
||||||
|
em.persist(cie);
|
||||||
|
c_id = cie.getId();
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Rev 3
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
re2 = em.find(ReferencedEntity.class, re_id2);
|
||||||
|
cie = em.find(ChildIngEntity.class, c_id);
|
||||||
|
|
||||||
|
cie.setReferenced(re2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferencedEntityHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(ReferencedEntity.class, re_id1, "referencing");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(2, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(ReferencedEntity.class, re_id1, "referencing");
|
||||||
|
assertEquals(1, list.size()); // initially referencing collection is null
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(ReferencedEntity.class, re_id2, "referencing");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(3), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.components.Component1;
|
||||||
|
import org.hibernate.envers.test.entities.components.Component2;
|
||||||
|
import org.hibernate.envers.test.entities.components.ComponentTestEntity;
|
||||||
|
import org.hibernate.envers.test.integration.collection.mapkey.ComponentMapKeyEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedComponentMapKey extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer cmke_id;
|
||||||
|
|
||||||
|
private Integer cte1_id;
|
||||||
|
private Integer cte2_id;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(ComponentMapKeyEntity.class);
|
||||||
|
cfg.addAnnotatedClass(ComponentTestEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
ComponentMapKeyEntity imke = new ComponentMapKeyEntity();
|
||||||
|
|
||||||
|
// Revision 1 (intialy 1 mapping)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ComponentTestEntity cte1 = new ComponentTestEntity(new Component1("x1", "y2"), new Component2("a1", "b2"));
|
||||||
|
ComponentTestEntity cte2 = new ComponentTestEntity(new Component1("x1", "y2"), new Component2("a1", "b2"));
|
||||||
|
|
||||||
|
em.persist(cte1);
|
||||||
|
em.persist(cte2);
|
||||||
|
|
||||||
|
imke.getIdmap().put(cte1.getComp1(), cte1);
|
||||||
|
|
||||||
|
em.persist(imke);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2 (sse1: adding 1 mapping)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
cte2 = em.find(ComponentTestEntity.class, cte2.getId());
|
||||||
|
imke = em.find(ComponentMapKeyEntity.class, imke.getId());
|
||||||
|
|
||||||
|
imke.getIdmap().put(cte2.getComp1(), cte2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
cmke_id = imke.getId();
|
||||||
|
|
||||||
|
cte1_id = cte1.getId();
|
||||||
|
cte2_id = cte2.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedMapEntity() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(ComponentMapKeyEntity.class, cmke_id, "idmap");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(ComponentMapKeyEntity.class,
|
||||||
|
cmke_id, "idmap");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedComponentEntity() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(ComponentTestEntity.class,
|
||||||
|
cte1_id, "comp1");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(ComponentTestEntity.class, cte1_id,
|
||||||
|
"comp1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(ComponentTestEntity.class, cte2_id, "comp1");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(ComponentTestEntity.class, cte2_id, "comp1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.components.Component1;
|
||||||
|
import org.hibernate.envers.test.entities.components.Component2;
|
||||||
|
import org.hibernate.envers.test.entities.components.ComponentTestEntity;
|
||||||
|
import org.hibernate.envers.test.tools.TestTools;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedComponents extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer id1;
|
||||||
|
private Integer id2;
|
||||||
|
private Integer id3;
|
||||||
|
private Integer id4;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(ComponentTestEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
// Revision 1
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ComponentTestEntity cte1 = new ComponentTestEntity(new Component1("a", "b"), new Component2("x", "y"));
|
||||||
|
ComponentTestEntity cte2 = new ComponentTestEntity(new Component1("a2", "b2"), new Component2("x2", "y2"));
|
||||||
|
ComponentTestEntity cte3 = new ComponentTestEntity(new Component1("a3", "b3"), new Component2("x3", "y3"));
|
||||||
|
ComponentTestEntity cte4 = new ComponentTestEntity(null, null);
|
||||||
|
|
||||||
|
em.persist(cte1);
|
||||||
|
em.persist(cte2);
|
||||||
|
em.persist(cte3);
|
||||||
|
em.persist(cte4);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2
|
||||||
|
em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
cte1 = em.find(ComponentTestEntity.class, cte1.getId());
|
||||||
|
cte2 = em.find(ComponentTestEntity.class, cte2.getId());
|
||||||
|
cte3 = em.find(ComponentTestEntity.class, cte3.getId());
|
||||||
|
cte4 = em.find(ComponentTestEntity.class, cte4.getId());
|
||||||
|
|
||||||
|
cte1.setComp1(new Component1("a'", "b'"));
|
||||||
|
cte2.getComp1().setStr1("a2'");
|
||||||
|
cte3.getComp2().setStr6("y3'");
|
||||||
|
cte4.setComp1(new Component1());
|
||||||
|
cte4.getComp1().setStr1("n");
|
||||||
|
cte4.setComp2(new Component2());
|
||||||
|
cte4.getComp2().setStr5("m");
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 3
|
||||||
|
em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
cte1 = em.find(ComponentTestEntity.class, cte1.getId());
|
||||||
|
cte2 = em.find(ComponentTestEntity.class, cte2.getId());
|
||||||
|
cte3 = em.find(ComponentTestEntity.class, cte3.getId());
|
||||||
|
cte4 = em.find(ComponentTestEntity.class, cte4.getId());
|
||||||
|
|
||||||
|
cte1.setComp2(new Component2("x'", "y'"));
|
||||||
|
cte3.getComp1().setStr2("b3'");
|
||||||
|
cte4.setComp1(null);
|
||||||
|
cte4.setComp2(null);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 4
|
||||||
|
em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
cte2 = em.find(ComponentTestEntity.class, cte2.getId());
|
||||||
|
|
||||||
|
em.remove(cte2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
id1 = cte1.getId();
|
||||||
|
id2 = cte2.getId();
|
||||||
|
id3 = cte3.getId();
|
||||||
|
id4 = cte4.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testModFlagProperties() {
|
||||||
|
assertEquals(TestTools.makeSet("comp1_MOD"),
|
||||||
|
TestTools.extractModProperties(getCfg().getClassMapping(
|
||||||
|
"org.hibernate.envers.test.entities.components.ComponentTestEntity_AUD")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = QueryException.class)
|
||||||
|
public void testHasChangedNotAudited() throws Exception {
|
||||||
|
queryForPropertyHasChanged(ComponentTestEntity.class, id1, "comp2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedId1() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(ComponentTestEntity.class, id1, "comp1");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(ComponentTestEntity.class, id1, "comp1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedId2() throws Exception {
|
||||||
|
List list = queryForPropertyHasChangedWithDeleted(ComponentTestEntity.class, id2, "comp1");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 2, 4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChangedWithDeleted(ComponentTestEntity.class, id2, "comp1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedId3() throws Exception {
|
||||||
|
List list = queryForPropertyHasChangedWithDeleted(ComponentTestEntity.class, id3, "comp1");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChangedWithDeleted(ComponentTestEntity.class, id3, "comp1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedId4() throws Exception {
|
||||||
|
List list = queryForPropertyHasChangedWithDeleted(ComponentTestEntity.class, id4, "comp1");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(2, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChangedWithDeleted(ComponentTestEntity.class, id4, "comp1");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.customtype.Component;
|
||||||
|
import org.hibernate.envers.test.entities.customtype.CompositeCustomTypeEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedCompositeCustom extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer ccte_id;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(CompositeCustomTypeEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
CompositeCustomTypeEntity ccte = new CompositeCustomTypeEntity();
|
||||||
|
|
||||||
|
// Revision 1 (persisting 1 entity)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ccte.setComponent(new Component("a", 1));
|
||||||
|
|
||||||
|
em.persist(ccte);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2 (changing the component)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ccte = em.find(CompositeCustomTypeEntity.class, ccte.getId());
|
||||||
|
|
||||||
|
ccte.getComponent().setProp1("b");
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 3 (replacing the component)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ccte = em.find(CompositeCustomTypeEntity.class, ccte.getId());
|
||||||
|
|
||||||
|
ccte.setComponent(new Component("c", 3));
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
ccte_id = ccte.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(CompositeCustomTypeEntity.class,ccte_id, "component");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 2, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(CompositeCustomTypeEntity.class,ccte_id, "component");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,260 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.onetomany.detached.DoubleListJoinColumnBidirectionalRefEdEntity1;
|
||||||
|
import org.hibernate.envers.test.entities.onetomany.detached.DoubleListJoinColumnBidirectionalRefEdEntity2;
|
||||||
|
import org.hibernate.envers.test.entities.onetomany.detached.DoubleListJoinColumnBidirectionalRefIngEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for a double "fake" bidirectional mapping where one side uses @OneToMany+@JoinColumn
|
||||||
|
* (and thus owns the relation), and the other uses a @ManyToOne(insertable=false, updatable=false).
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedDoubleJoinColumnBidirectionalList extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer ed1_1_id;
|
||||||
|
private Integer ed2_1_id;
|
||||||
|
private Integer ed1_2_id;
|
||||||
|
private Integer ed2_2_id;
|
||||||
|
|
||||||
|
private Integer ing1_id;
|
||||||
|
private Integer ing2_id;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(DoubleListJoinColumnBidirectionalRefIngEntity.class);
|
||||||
|
cfg.addAnnotatedClass(DoubleListJoinColumnBidirectionalRefEdEntity1.class);
|
||||||
|
cfg.addAnnotatedClass(DoubleListJoinColumnBidirectionalRefEdEntity2.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void createData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity1 ed1_1 = new DoubleListJoinColumnBidirectionalRefEdEntity1("ed1_1", null);
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity1 ed1_2 = new DoubleListJoinColumnBidirectionalRefEdEntity1("ed1_2", null);
|
||||||
|
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity2 ed2_1 = new DoubleListJoinColumnBidirectionalRefEdEntity2("ed2_1", null);
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity2 ed2_2 = new DoubleListJoinColumnBidirectionalRefEdEntity2("ed2_2", null);
|
||||||
|
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity ing1 = new DoubleListJoinColumnBidirectionalRefIngEntity("coll1");
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity ing2 = new DoubleListJoinColumnBidirectionalRefIngEntity("coll2");
|
||||||
|
|
||||||
|
// Revision 1 (ing1: ed1_1, ed2_1, ing2: ed1_2, ed2_2)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ing1.getReferences1().add(ed1_1);
|
||||||
|
ing1.getReferences2().add(ed2_1);
|
||||||
|
|
||||||
|
ing2.getReferences1().add(ed1_2);
|
||||||
|
ing2.getReferences2().add(ed2_2);
|
||||||
|
|
||||||
|
em.persist(ed1_1);
|
||||||
|
em.persist(ed1_2);
|
||||||
|
em.persist(ed2_1);
|
||||||
|
em.persist(ed2_2);
|
||||||
|
em.persist(ing1);
|
||||||
|
em.persist(ing2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2 (ing1: ed1_1, ed1_2, ed2_1, ed2_2)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ing1 = em.find(DoubleListJoinColumnBidirectionalRefIngEntity.class, ing1.getId());
|
||||||
|
ing2 = em.find(DoubleListJoinColumnBidirectionalRefIngEntity.class, ing2.getId());
|
||||||
|
ed1_1 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_1.getId());
|
||||||
|
ed1_2 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_2.getId());
|
||||||
|
ed2_1 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_1.getId());
|
||||||
|
ed2_2 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_2.getId());
|
||||||
|
|
||||||
|
ing2.getReferences1().clear();
|
||||||
|
ing2.getReferences2().clear();
|
||||||
|
|
||||||
|
ing1.getReferences1().add(ed1_2);
|
||||||
|
ing1.getReferences2().add(ed2_2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.clear();
|
||||||
|
|
||||||
|
// Revision 3 (ing1: ed1_1, ed1_2, ed2_1, ed2_2)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ing1 = em.find(DoubleListJoinColumnBidirectionalRefIngEntity.class, ing1.getId());
|
||||||
|
ing2 = em.find(DoubleListJoinColumnBidirectionalRefIngEntity.class, ing2.getId());
|
||||||
|
ed1_1 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_1.getId());
|
||||||
|
ed1_2 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_2.getId());
|
||||||
|
ed2_1 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_1.getId());
|
||||||
|
ed2_2 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_2.getId());
|
||||||
|
|
||||||
|
ed1_1.setData("ed1_1 bis");
|
||||||
|
ed2_2.setData("ed2_2 bis");
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.clear();
|
||||||
|
|
||||||
|
// Revision 4 (ing1: ed2_2, ing2: ed2_1, ed1_1, ed1_2)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ing1 = em.find(DoubleListJoinColumnBidirectionalRefIngEntity.class, ing1.getId());
|
||||||
|
ing2 = em.find(DoubleListJoinColumnBidirectionalRefIngEntity.class, ing2.getId());
|
||||||
|
ed1_1 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_1.getId());
|
||||||
|
ed1_2 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_2.getId());
|
||||||
|
ed2_1 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_1.getId());
|
||||||
|
ed2_2 = em.find(DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_2.getId());
|
||||||
|
|
||||||
|
ing1.getReferences1().clear();
|
||||||
|
ing2.getReferences1().add(ed1_1);
|
||||||
|
ing2.getReferences1().add(ed1_2);
|
||||||
|
|
||||||
|
ing1.getReferences2().remove(ed2_1);
|
||||||
|
ing2.getReferences2().add(ed2_1);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.clear();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
ing1_id = ing1.getId();
|
||||||
|
ing2_id = ing2.getId();
|
||||||
|
|
||||||
|
ed1_1_id = ed1_1.getId();
|
||||||
|
ed1_2_id = ed1_2.getId();
|
||||||
|
ed2_1_id = ed2_1.getId();
|
||||||
|
ed2_2_id = ed2_2.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOwnerHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_1_id,
|
||||||
|
"owner");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_1_id,
|
||||||
|
"owner");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_2_id,
|
||||||
|
"owner");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 2, 4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity1.class, ed1_2_id,
|
||||||
|
"owner");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOwnerSecEntityHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_1_id,
|
||||||
|
"owner");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_1_id,
|
||||||
|
"owner");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_2_id,
|
||||||
|
"owner");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefEdEntity2.class, ed2_2_id,
|
||||||
|
"owner");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(3), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferences1HasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity.class, ing1_id,
|
||||||
|
"references1");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 2, 4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity.class, ing2_id,
|
||||||
|
"references1");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 2, 4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity.class, ing1_id,
|
||||||
|
"references1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity.class, ing2_id,
|
||||||
|
"references1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferences2HasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity.class, ing1_id,
|
||||||
|
"references2");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 2, 4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity.class, ing2_id,
|
||||||
|
"references2");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 2, 4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity.class, ing1_id,
|
||||||
|
"references2");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(
|
||||||
|
DoubleListJoinColumnBidirectionalRefIngEntity.class, ing2_id,
|
||||||
|
"references2");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.collection.EnumSetEntity;
|
||||||
|
import org.hibernate.envers.test.entities.collection.EnumSetEntity.E1;
|
||||||
|
import org.hibernate.envers.test.entities.collection.EnumSetEntity.E2;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedEnumSet extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer sse1_id;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(EnumSetEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
EnumSetEntity sse1 = new EnumSetEntity();
|
||||||
|
|
||||||
|
// Revision 1 (sse1: initialy 1 element)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sse1.getEnums1().add(E1.X);
|
||||||
|
sse1.getEnums2().add(E2.A);
|
||||||
|
|
||||||
|
em.persist(sse1);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2 (sse1: adding 1 element/removing a non-existing element)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sse1 = em.find(EnumSetEntity.class, sse1.getId());
|
||||||
|
|
||||||
|
sse1.getEnums1().add(E1.Y);
|
||||||
|
sse1.getEnums2().remove(E2.B);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 3 (sse1: removing 1 element/adding an exisiting element)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sse1 = em.find(EnumSetEntity.class, sse1.getId());
|
||||||
|
|
||||||
|
sse1.getEnums1().remove(E1.X);
|
||||||
|
sse1.getEnums2().add(E2.A);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
sse1_id = sse1.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(EnumSetEntity.class, sse1_id,
|
||||||
|
"enums1");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 2, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(EnumSetEntity.class, sse1_id,
|
||||||
|
"enums2");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(EnumSetEntity.class, sse1_id,
|
||||||
|
"enums1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(EnumSetEntity.class, sse1_id,
|
||||||
|
"enums2");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(2, 3), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,274 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||||
|
import org.hibernate.envers.test.entities.components.Component1;
|
||||||
|
import org.hibernate.envers.test.entities.components.Component2;
|
||||||
|
import org.hibernate.envers.test.integration.modifiedflags.entities.PartialModifiedFlagsEntity;
|
||||||
|
import org.hibernate.envers.test.integration.modifiedflags.entities.WithModifiedFlagReferencingEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedForDefaultNotUsing extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private static final int entityId = 1;
|
||||||
|
private static final int refEntityId = 1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean forceModifiedFlags() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(PartialModifiedFlagsEntity.class);
|
||||||
|
cfg.addAnnotatedClass(WithModifiedFlagReferencingEntity.class);
|
||||||
|
cfg.addAnnotatedClass(StrTestEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
|
||||||
|
PartialModifiedFlagsEntity entity =
|
||||||
|
new PartialModifiedFlagsEntity(entityId);
|
||||||
|
|
||||||
|
// Revision 1
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
em.persist(entity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
entity.setData("data1");
|
||||||
|
entity = em.merge(entity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 3
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
entity.setComp1(new Component1("str1", "str2"));
|
||||||
|
entity = em.merge(entity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 4
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
entity.setComp2(new Component2("str1", "str2"));
|
||||||
|
entity = em.merge(entity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 5
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
WithModifiedFlagReferencingEntity withModifiedFlagReferencingEntity = new WithModifiedFlagReferencingEntity(refEntityId, "first");
|
||||||
|
withModifiedFlagReferencingEntity.setReference(entity);
|
||||||
|
em.persist(withModifiedFlagReferencingEntity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 6
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
withModifiedFlagReferencingEntity = em.find(WithModifiedFlagReferencingEntity.class, refEntityId);
|
||||||
|
withModifiedFlagReferencingEntity.setReference(null);
|
||||||
|
withModifiedFlagReferencingEntity.setSecondReference(entity);
|
||||||
|
em.merge(withModifiedFlagReferencingEntity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 7
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
entity.getStringSet().add("firstElement");
|
||||||
|
entity.getStringSet().add("secondElement");
|
||||||
|
entity = em.merge(entity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 8
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
entity.getStringSet().remove("secondElement");
|
||||||
|
entity.getStringMap().put("someKey", "someValue");
|
||||||
|
entity = em.merge(entity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 9 - main entity doesn't change
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
StrTestEntity strTestEntity = new StrTestEntity("first");
|
||||||
|
em.persist(strTestEntity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 10
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
entity.getEntitiesSet().add(strTestEntity);
|
||||||
|
entity = em.merge(entity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 11
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
entity.getEntitiesSet().remove(strTestEntity);
|
||||||
|
entity.getEntitiesMap().put("someKey", strTestEntity);
|
||||||
|
em.merge(entity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 12 - main entity doesn't change
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
strTestEntity.setStr("second");
|
||||||
|
em.merge(strTestEntity);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRevisionsCounts() {
|
||||||
|
assertEquals(Arrays.asList((Number) 1, 2, 3, 4, 5, 6, 7, 8, 10, 11),
|
||||||
|
getAuditReader()
|
||||||
|
.getRevisions(PartialModifiedFlagsEntity.class,
|
||||||
|
entityId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedData() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "data");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(2), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedComp1() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "comp1");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(3), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = QueryException.class)
|
||||||
|
public void testHasChangedComp2() throws Exception {
|
||||||
|
queryForPropertyHasChanged(PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "comp2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedReferencing() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "referencing");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(5, 6), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = QueryException.class)
|
||||||
|
public void testHasChangedReferencing2() throws Exception {
|
||||||
|
queryForPropertyHasChanged(PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "referencing2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedStringSet() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "stringSet");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 7, 8), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedStringMap() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "stringMap");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 8), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedStringSetAndMap() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "stringSet", "stringMap");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 8), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedEntitiesSet() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "entitiesSet");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 10, 11), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedEntitiesMap() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "entitiesMap");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 11), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedEntitiesSetAndMap() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(
|
||||||
|
PartialModifiedFlagsEntity.class,
|
||||||
|
entityId, "entitiesSet", "entitiesMap");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 11), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||||
|
import org.hibernate.envers.test.integration.collection.mapkey.IdMapKeyEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedIdMapKey extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer imke_id;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(IdMapKeyEntity.class);
|
||||||
|
cfg.addAnnotatedClass(StrTestEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
IdMapKeyEntity imke = new IdMapKeyEntity();
|
||||||
|
|
||||||
|
// Revision 1 (intialy 1 mapping)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
StrTestEntity ste1 = new StrTestEntity("x");
|
||||||
|
StrTestEntity ste2 = new StrTestEntity("y");
|
||||||
|
|
||||||
|
em.persist(ste1);
|
||||||
|
em.persist(ste2);
|
||||||
|
|
||||||
|
imke.getIdmap().put(ste1.getId(), ste1);
|
||||||
|
|
||||||
|
em.persist(imke);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2 (sse1: adding 1 mapping)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ste2 = em.find(StrTestEntity.class, ste2.getId());
|
||||||
|
imke = em.find(IdMapKeyEntity.class, imke.getId());
|
||||||
|
|
||||||
|
imke.getIdmap().put(ste2.getId(), ste2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
imke_id = imke.getId();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(IdMapKeyEntity.class, imke_id,
|
||||||
|
"idmap");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(IdMapKeyEntity.class, imke_id,
|
||||||
|
"idmap");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||||
|
import org.hibernate.envers.test.entities.components.relations.ManyToOneComponent;
|
||||||
|
import org.hibernate.envers.test.entities.components.relations.ManyToOneComponentTestEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedManyToOneInComponent extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer mtocte_id1;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(ManyToOneComponentTestEntity.class);
|
||||||
|
cfg.addAnnotatedClass(StrTestEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
// Revision 1
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
StrTestEntity ste1 = new StrTestEntity();
|
||||||
|
ste1.setStr("str1");
|
||||||
|
|
||||||
|
StrTestEntity ste2 = new StrTestEntity();
|
||||||
|
ste2.setStr("str2");
|
||||||
|
|
||||||
|
em.persist(ste1);
|
||||||
|
em.persist(ste2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2
|
||||||
|
em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
ManyToOneComponentTestEntity mtocte1 = new ManyToOneComponentTestEntity(new ManyToOneComponent(ste1, "data1"));
|
||||||
|
|
||||||
|
em.persist(mtocte1);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 3
|
||||||
|
em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
mtocte1 = em.find(ManyToOneComponentTestEntity.class, mtocte1.getId());
|
||||||
|
mtocte1.getComp1().setEntity(ste2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
mtocte_id1 = mtocte1.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedId1() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(ManyToOneComponentTestEntity.class,
|
||||||
|
mtocte_id1, "comp1");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(2, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(ManyToOneComponentTestEntity.class,
|
||||||
|
mtocte_id1, "comp1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.integration.inheritance.joined.notownedrelation.Address;
|
||||||
|
import org.hibernate.envers.test.integration.inheritance.joined.notownedrelation.Contact;
|
||||||
|
import org.hibernate.envers.test.integration.inheritance.joined.notownedrelation.PersonalContact;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedNotOwnedBidirectional extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Long pc_id;
|
||||||
|
private Long a1_id;
|
||||||
|
private Long a2_id;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(Address.class);
|
||||||
|
cfg.addAnnotatedClass(Contact.class);
|
||||||
|
cfg.addAnnotatedClass(PersonalContact.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
pc_id = 1l;
|
||||||
|
a1_id = 10l;
|
||||||
|
a2_id = 100l;
|
||||||
|
|
||||||
|
// Rev 1
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
PersonalContact pc = new PersonalContact(pc_id, "e", "f");
|
||||||
|
|
||||||
|
Address a1 = new Address(a1_id, "a1");
|
||||||
|
a1.setContact(pc);
|
||||||
|
|
||||||
|
em.persist(pc);
|
||||||
|
em.persist(a1);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Rev 2
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
pc = em.find(PersonalContact.class, pc_id);
|
||||||
|
|
||||||
|
Address a2 = new Address(a2_id, "a2");
|
||||||
|
a2.setContact(pc);
|
||||||
|
|
||||||
|
em.persist(a2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferencedEntityHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(PersonalContact.class, pc_id,
|
||||||
|
"addresses");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(Address.class, a1_id, "contact");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(Address.class, a2_id, "contact");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(2), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.query.AuditEntity;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.integration.basic.BasicTestEntity1;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedNullProperties extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer id1;
|
||||||
|
private Integer id2;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(BasicTestEntity1.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer addNewEntity(String str, long lng) {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
BasicTestEntity1 bte1 = new BasicTestEntity1(str, lng);
|
||||||
|
em.persist(bte1);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
return bte1.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void modifyEntity(Integer id, String str, long lng) {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
BasicTestEntity1 bte1 = em.find(BasicTestEntity1.class, id);
|
||||||
|
bte1.setLong1(lng);
|
||||||
|
bte1.setStr1(str);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
id1 = addNewEntity("x", 1); // rev 1
|
||||||
|
id2 = addNewEntity(null, 20); // rev 2
|
||||||
|
|
||||||
|
modifyEntity(id1, null, 1); // rev 3
|
||||||
|
modifyEntity(id2, "y2", 20); // rev 4
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChangedWithDeleted(BasicTestEntity1.class,
|
||||||
|
id1, "str1");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChangedWithDeleted(BasicTestEntity1.class,
|
||||||
|
id1, "long1");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChangedWithDeleted(BasicTestEntity1.class,
|
||||||
|
id2, "str1");
|
||||||
|
// str1 property was null before insert and after insert so in a way it didn't change - is it a good way to go?
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(4), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChangedWithDeleted(BasicTestEntity1.class,
|
||||||
|
id2, "long1");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = getAuditReader().createQuery().forRevisionsOfEntity(BasicTestEntity1.class, false, true)
|
||||||
|
.add(AuditEntity.property("str1").hasChanged())
|
||||||
|
.add(AuditEntity.property("long1").hasChanged())
|
||||||
|
.getResultList();
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||||
|
import org.hibernate.envers.test.entities.components.relations.OneToManyComponent;
|
||||||
|
import org.hibernate.envers.test.entities.components.relations.OneToManyComponentTestEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedOneToManyInComponent extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer otmcte_id1;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(OneToManyComponentTestEntity.class);
|
||||||
|
cfg.addAnnotatedClass(StrTestEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
// Revision 1
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
StrTestEntity ste1 = new StrTestEntity();
|
||||||
|
ste1.setStr("str1");
|
||||||
|
|
||||||
|
StrTestEntity ste2 = new StrTestEntity();
|
||||||
|
ste2.setStr("str2");
|
||||||
|
|
||||||
|
em.persist(ste1);
|
||||||
|
em.persist(ste2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2
|
||||||
|
em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
OneToManyComponentTestEntity otmcte1 = new OneToManyComponentTestEntity(new OneToManyComponent("data1"));
|
||||||
|
otmcte1.getComp1().getEntities().add(ste1);
|
||||||
|
|
||||||
|
em.persist(otmcte1);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 3
|
||||||
|
em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
otmcte1 = em.find(OneToManyComponentTestEntity.class, otmcte1.getId());
|
||||||
|
otmcte1.getComp1().getEntities().add(ste2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
otmcte_id1 = otmcte1.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedId1() throws Exception {
|
||||||
|
List list =
|
||||||
|
queryForPropertyHasChanged(OneToManyComponentTestEntity.class,
|
||||||
|
otmcte_id1, "comp1");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(2, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(OneToManyComponentTestEntity.class,
|
||||||
|
otmcte_id1, "comp1");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.collection.StringMapEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedStringMap extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer sme1_id;
|
||||||
|
private Integer sme2_id;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(StringMapEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
StringMapEntity sme1 = new StringMapEntity();
|
||||||
|
StringMapEntity sme2 = new StringMapEntity();
|
||||||
|
|
||||||
|
// Revision 1 (sme1: initialy empty, sme2: initialy 1 mapping)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sme2.getStrings().put("1", "a");
|
||||||
|
|
||||||
|
em.persist(sme1);
|
||||||
|
em.persist(sme2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2 (sme1: adding 2 mappings, sme2: no changes)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sme1 = em.find(StringMapEntity.class, sme1.getId());
|
||||||
|
sme2 = em.find(StringMapEntity.class, sme2.getId());
|
||||||
|
|
||||||
|
sme1.getStrings().put("1", "a");
|
||||||
|
sme1.getStrings().put("2", "b");
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 3 (sme1: removing an existing mapping, sme2: replacing a value)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sme1 = em.find(StringMapEntity.class, sme1.getId());
|
||||||
|
sme2 = em.find(StringMapEntity.class, sme2.getId());
|
||||||
|
|
||||||
|
sme1.getStrings().remove("1");
|
||||||
|
sme2.getStrings().put("1", "b");
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// No revision (sme1: removing a non-existing mapping, sme2: replacing with the same value)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sme1 = em.find(StringMapEntity.class, sme1.getId());
|
||||||
|
sme2 = em.find(StringMapEntity.class, sme2.getId());
|
||||||
|
|
||||||
|
sme1.getStrings().remove("3");
|
||||||
|
sme2.getStrings().put("1", "b");
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
sme1_id = sme1.getId();
|
||||||
|
sme2_id = sme2.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(StringMapEntity.class, sme1_id,
|
||||||
|
"strings");
|
||||||
|
assertEquals(3, list.size());
|
||||||
|
assertEquals(makeList(1, 2, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(StringMapEntity.class, sme2_id,
|
||||||
|
"strings");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(StringMapEntity.class, sme1_id,
|
||||||
|
"strings");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(StringMapEntity.class, sme2_id,
|
||||||
|
"strings");
|
||||||
|
assertEquals(0, list.size()); // in rev 2 there was no version generated for sme2_id
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.collection.StringSetEntity;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedStringSet extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer sse1_id;
|
||||||
|
private Integer sse2_id;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(StringSetEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
StringSetEntity sse1 = new StringSetEntity();
|
||||||
|
StringSetEntity sse2 = new StringSetEntity();
|
||||||
|
|
||||||
|
// Revision 1 (sse1: initialy empty, sse2: initialy 2 elements)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sse2.getStrings().add("sse2_string1");
|
||||||
|
sse2.getStrings().add("sse2_string2");
|
||||||
|
|
||||||
|
em.persist(sse1);
|
||||||
|
em.persist(sse2);
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2 (sse1: adding 2 elements, sse2: adding an existing element)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sse1 = em.find(StringSetEntity.class, sse1.getId());
|
||||||
|
sse2 = em.find(StringSetEntity.class, sse2.getId());
|
||||||
|
|
||||||
|
sse1.getStrings().add("sse1_string1");
|
||||||
|
sse1.getStrings().add("sse1_string2");
|
||||||
|
|
||||||
|
sse2.getStrings().add("sse2_string1");
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 3 (sse1: removing a non-existing element, sse2: removing one element)
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
sse1 = em.find(StringSetEntity.class, sse1.getId());
|
||||||
|
sse2 = em.find(StringSetEntity.class, sse2.getId());
|
||||||
|
|
||||||
|
sse1.getStrings().remove("sse1_string3");
|
||||||
|
sse2.getStrings().remove("sse2_string1");
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
sse1_id = sse1.getId();
|
||||||
|
sse2_id = sse2.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(StringSetEntity.class, sse1_id,
|
||||||
|
"strings");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChanged(StringSetEntity.class, sse2_id,
|
||||||
|
"strings");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 3), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(StringSetEntity.class, sse1_id,
|
||||||
|
"strings");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
|
||||||
|
list = queryForPropertyHasNotChanged(StringSetEntity.class, sse2_id,
|
||||||
|
"strings");
|
||||||
|
assertEquals(0, list.size());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.integration.basic.BasicTestEntity2;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class HasChangedUnversionedProperties extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer id1;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(BasicTestEntity2.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer addNewEntity(String str1, String str2) {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
BasicTestEntity2 bte2 = new BasicTestEntity2(str1, str2);
|
||||||
|
em.persist(bte2);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
return bte2.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void modifyEntity(Integer id, String str1, String str2) {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
BasicTestEntity2 bte2 = em.find(BasicTestEntity2.class, id);
|
||||||
|
bte2.setStr1(str1);
|
||||||
|
bte2.setStr2(str2);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
id1 = addNewEntity("x", "a"); // rev 1
|
||||||
|
modifyEntity(id1, "x", "a"); // no rev
|
||||||
|
modifyEntity(id1, "y", "b"); // rev 2
|
||||||
|
modifyEntity(id1, "y", "c"); // no rev
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChangedQuery() throws Exception {
|
||||||
|
List list = queryForPropertyHasChanged(BasicTestEntity2.class,
|
||||||
|
id1, "str1");
|
||||||
|
assertEquals(2, list.size());
|
||||||
|
assertEquals(makeList(1, 2), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = QueryException.class)
|
||||||
|
public void testExceptionOnHasChangedQuery() throws Exception {
|
||||||
|
queryForPropertyHasChangedWithDeleted(BasicTestEntity2.class,
|
||||||
|
id1, "str2");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
|
import org.hibernate.envers.query.AuditEntity;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.integration.basic.BasicTestEntity1;
|
||||||
|
import org.hibernate.envers.test.tools.TestTools;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.extractRevisionNumbers;
|
||||||
|
import static org.hibernate.envers.test.tools.TestTools.makeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
public class ModifiedFlagSuffix extends AbstractModifiedFlagsEntityTest {
|
||||||
|
private Integer id1;
|
||||||
|
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(BasicTestEntity1.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addConfigurationProperties(Properties configuration) {
|
||||||
|
super.addConfigurationProperties(configuration);
|
||||||
|
configuration
|
||||||
|
.setProperty(GlobalConfiguration.MODIFIED_FLAG_SUFFIX_PROPERTY,
|
||||||
|
"_CHANGED");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer addNewEntity(String str, long lng) {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
BasicTestEntity1 bte1 = new BasicTestEntity1(str, lng);
|
||||||
|
em.persist(bte1);
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
return bte1.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
id1 = addNewEntity("x", 1); // rev 1
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testModFlagProperties() {
|
||||||
|
assertEquals(TestTools.makeSet("str1_CHANGED", "long1_CHANGED"),
|
||||||
|
TestTools.extractModProperties(getCfg().getClassMapping(
|
||||||
|
"org.hibernate.envers.test.integration.basic.BasicTestEntity1_AUD"),
|
||||||
|
"_CHANGED"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasChanged() throws Exception {
|
||||||
|
List list = queryForPropertyHasChangedWithDeleted(BasicTestEntity1.class,
|
||||||
|
id1, "str1");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = queryForPropertyHasChangedWithDeleted(BasicTestEntity1.class,
|
||||||
|
id1, "long1");
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
|
||||||
|
list = getAuditReader().createQuery().forRevisionsOfEntity(BasicTestEntity1.class, false, true)
|
||||||
|
.add(AuditEntity.property("str1").hasChanged())
|
||||||
|
.add(AuditEntity.property("long1").hasChanged())
|
||||||
|
.getResultList();
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(makeList(1), extractRevisionNumbers(list));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags.entities;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||||
|
import org.hibernate.envers.test.entities.components.Component1;
|
||||||
|
import org.hibernate.envers.test.entities.components.Component2;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Michal Skowronek (mskowr at o2 dot pl)
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Audited(withModifiedFlag = false)
|
||||||
|
public class PartialModifiedFlagsEntity {
|
||||||
|
@Id
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@Audited(withModifiedFlag = true)
|
||||||
|
private String data;
|
||||||
|
|
||||||
|
@Audited(withModifiedFlag = true)
|
||||||
|
@Embedded
|
||||||
|
private Component1 comp1;
|
||||||
|
|
||||||
|
@Audited(withModifiedFlag = false)
|
||||||
|
@Embedded
|
||||||
|
private Component2 comp2;
|
||||||
|
|
||||||
|
@Audited(withModifiedFlag = true)
|
||||||
|
@OneToOne(mappedBy="reference")
|
||||||
|
private WithModifiedFlagReferencingEntity referencing;
|
||||||
|
|
||||||
|
@Audited(withModifiedFlag = false)
|
||||||
|
@OneToOne(mappedBy="secondReference")
|
||||||
|
private WithModifiedFlagReferencingEntity referencing2;
|
||||||
|
|
||||||
|
@Audited(withModifiedFlag = true)
|
||||||
|
@ElementCollection
|
||||||
|
private Set<String> stringSet = new HashSet<String>();
|
||||||
|
|
||||||
|
@Audited(withModifiedFlag = true)
|
||||||
|
@ManyToMany
|
||||||
|
@CollectionTable(name = "ENTITIESSET")
|
||||||
|
private Set<StrTestEntity> entitiesSet = new HashSet<StrTestEntity>();
|
||||||
|
|
||||||
|
@Audited(withModifiedFlag = true)
|
||||||
|
@ElementCollection
|
||||||
|
private Map<String, String> stringMap = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@Audited(withModifiedFlag = true)
|
||||||
|
@ManyToMany
|
||||||
|
@CollectionTable(name = "ENTITIESMAP")
|
||||||
|
private Map<String, StrTestEntity> entitiesMap =
|
||||||
|
new HashMap<String, StrTestEntity>();
|
||||||
|
|
||||||
|
public PartialModifiedFlagsEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public PartialModifiedFlagsEntity(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WithModifiedFlagReferencingEntity getReferencing() {
|
||||||
|
return referencing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReferencing(WithModifiedFlagReferencingEntity referencing) {
|
||||||
|
this.referencing = referencing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WithModifiedFlagReferencingEntity getReferencing2() {
|
||||||
|
return referencing2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReferencing2(WithModifiedFlagReferencingEntity referencing) {
|
||||||
|
this.referencing2 = referencing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component1 getComp1() {
|
||||||
|
return comp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComp1(Component1 comp1) {
|
||||||
|
this.comp1 = comp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component2 getComp2() {
|
||||||
|
return comp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComp2(Component2 comp2) {
|
||||||
|
this.comp2 = comp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getStringSet() {
|
||||||
|
return stringSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringSet(Set<String> stringSet) {
|
||||||
|
this.stringSet = stringSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<StrTestEntity> getEntitiesSet() {
|
||||||
|
return entitiesSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEntitiesSet(Set<StrTestEntity> entitiesSet) {
|
||||||
|
this.entitiesSet = entitiesSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getStringMap() {
|
||||||
|
return stringMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringMap(Map<String, String> stringMap) {
|
||||||
|
this.stringMap = stringMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, StrTestEntity> getEntitiesMap() {
|
||||||
|
return entitiesMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEntitiesMap(Map<String, StrTestEntity> entitiesMap) {
|
||||||
|
this.entitiesMap = entitiesMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof PartialModifiedFlagsEntity)) return false;
|
||||||
|
|
||||||
|
PartialModifiedFlagsEntity that = (PartialModifiedFlagsEntity) o;
|
||||||
|
|
||||||
|
if (data != null ? !data.equals(that.data) : that.data != null) return false;
|
||||||
|
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result;
|
||||||
|
result = (id != null ? id.hashCode() : 0);
|
||||||
|
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.envers.test.integration.modifiedflags.entities;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Warski (adam at warski dot org)
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Audited(withModifiedFlag = true)
|
||||||
|
public class WithModifiedFlagReferencingEntity {
|
||||||
|
@Id
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String data;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private PartialModifiedFlagsEntity reference;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private PartialModifiedFlagsEntity secondReference;
|
||||||
|
|
||||||
|
public WithModifiedFlagReferencingEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public WithModifiedFlagReferencingEntity(Integer id, String data) {
|
||||||
|
this.id = id;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PartialModifiedFlagsEntity getReference() {
|
||||||
|
return reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReference(PartialModifiedFlagsEntity reference) {
|
||||||
|
this.reference = reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PartialModifiedFlagsEntity getSecondReference() {
|
||||||
|
return secondReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecondReference(PartialModifiedFlagsEntity reference) {
|
||||||
|
this.secondReference = reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof WithModifiedFlagReferencingEntity)) return false;
|
||||||
|
|
||||||
|
WithModifiedFlagReferencingEntity that = (WithModifiedFlagReferencingEntity) o;
|
||||||
|
|
||||||
|
if (data != null ? !data.equals(that.data) : that.data != null) return false;
|
||||||
|
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result;
|
||||||
|
result = (id != null ? id.hashCode() : 0);
|
||||||
|
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,9 +22,16 @@
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.envers.test.tools;
|
package org.hibernate.envers.test.tools;
|
||||||
|
import org.hibernate.envers.DefaultRevisionEntity;
|
||||||
|
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -71,4 +78,34 @@ public class TestTools {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Integer> extractRevisionNumbers(List queryResults) {
|
||||||
|
List<Integer> result = new ArrayList<Integer>();
|
||||||
|
for (Object queryResult : queryResults) {
|
||||||
|
result.add(((DefaultRevisionEntity) ((Object[]) queryResult)[1])
|
||||||
|
.getId());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<String> extractModProperties(
|
||||||
|
PersistentClass persistentClass) {
|
||||||
|
return extractModProperties(persistentClass,
|
||||||
|
GlobalConfiguration.DEFAULT_MODIFIED_FLAG_SUFFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<String> extractModProperties(
|
||||||
|
PersistentClass persistentClass, String suffix) {
|
||||||
|
Set<String> result = new HashSet<String>();
|
||||||
|
Iterator iterator = persistentClass.getPropertyIterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Property property = (Property) iterator.next();
|
||||||
|
String propertyName = property.getName();
|
||||||
|
if (propertyName.endsWith(suffix)) {
|
||||||
|
result.add(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue