Skip to content

Commit

Permalink
XWIKI-22782: Only save modified xobjects
Browse files Browse the repository at this point in the history
  • Loading branch information
tmortagne committed Jan 22, 2025
1 parent 2e4f1f7 commit 081a360
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.inject.Inject;
import javax.inject.Named;
Expand All @@ -29,6 +31,9 @@
import org.apache.commons.lang3.StringUtils;
import org.xwiki.component.annotation.Component;
import org.xwiki.configuration.ConfigurationSource;
import org.xwiki.model.EntityType;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.model.reference.EntityReferenceResolver;

import com.xpn.xwiki.internal.XWikiCfgConfigurationSource;

Expand All @@ -46,6 +51,10 @@ public class HibernateConfiguration
@Named(XWikiCfgConfigurationSource.ROLEHINT)
private ConfigurationSource xwikiConfiguration;

@Inject
@Named("relative")
private EntityReferenceResolver<String> resolver;

private String path;

/**
Expand Down Expand Up @@ -164,4 +173,20 @@ public List<String> getIgnoredMigrations()
{
return getList("xwiki.store.migration.ignored");
}

/**
* @return the local references of the classes for which we should apply a save optimization (save only the modified
* ones)
* @since 17.1.0RC1
* @since 16.10.3
*/
public Set<EntityReference> getOptimizedXObjectClasses()
{
List<String> references =
this.xwikiConfiguration.getProperty("xwiki.store.hibernate.optimizedObjectSave.classes", List.class);

return references != null
? references.stream().map(r -> this.resolver.resolve(r, EntityType.DOCUMENT)).collect(Collectors.toSet())
: null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,6 @@ public PropertyInterface get(String name) throws XWikiException
public void safeput(String name, PropertyInterface property)
{
addField(name, property);
if (property instanceof BaseProperty) {
((BaseProperty) property).setObject(this);
((BaseProperty) property).setName(name);
}
}

@Override
Expand Down Expand Up @@ -537,8 +533,13 @@ public void addField(String name, PropertyInterface element)
{
this.fields.put(name, element);

if (element instanceof BaseElement) {
((BaseElement) element).setOwnerDocument(getOwnerDocument());
element.setName(name);
if (element instanceof BaseElement baseElement) {
baseElement.setOwnerDocument(getOwnerDocument());

if (element instanceof BaseProperty baseProperty) {
baseProperty.setObject(this);
}
}
}

Expand Down Expand Up @@ -647,6 +648,8 @@ public BaseCollection clone()
}
collection.setFields(cfields);

collection.setDirty(isDirty());

return collection;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.Objects;

import javax.inject.Provider;

Expand All @@ -37,6 +38,7 @@
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.model.reference.EntityReferenceSerializer;
import org.xwiki.stability.Unstable;
import org.xwiki.store.merge.MergeManager;
import org.xwiki.store.merge.MergeManagerResult;

Expand Down Expand Up @@ -101,7 +103,35 @@ public abstract class BaseElement<R extends EntityReference> implements ElementI
private EntityReferenceSerializer<String> localUidStringEntityReferenceSerializer;

private ContextualLocalizationManager localization;


private transient boolean dirty = true;

/**
* @return true of the element was modified (or created)
* @since 17.1.0RC1
* @since 16.10.3
*/
@Unstable
public boolean isDirty()
{
return this.dirty;
}

/**
* @param dirty true of the element was modified (or created)
* @since 17.1.0RC1
* @since 16.10.3
*/
@Unstable
public void setDirty(boolean dirty)
{
this.dirty = dirty;

if (dirty && this.ownerDocument != null) {
this.ownerDocument.setMetaDataDirty(true);
}
}

/**
* @return a merge manager instance.
* @since 11.8RC1
Expand Down Expand Up @@ -161,12 +191,16 @@ public String getName()
}

@Override
public void setDocumentReference(DocumentReference reference)
public void setDocumentReference(DocumentReference documentReference)
{
// If the name is already set then reset it since we're now using a reference
this.documentReference = reference;
this.name = null;
this.referenceCache = null;
if (!Objects.equals(documentReference, this.documentReference)) {
// If the name is already set then reset it since we're now using a reference
this.documentReference = documentReference;
this.name = null;
this.referenceCache = null;

setDirty(true);
}
}

/**
Expand All @@ -185,8 +219,12 @@ public void setName(String name)
throw new IllegalStateException("BaseElement#setName could not be called when a reference has been set.");
}

this.name = name;
this.referenceCache = null;
if (!StringUtils.equals(name, this.name)) {
this.name = name;
this.referenceCache = null;

setDirty(true);
}
}

public String getPrettyName()
Expand Down Expand Up @@ -349,6 +387,8 @@ public BaseElement clone()
}

element.setPrettyName(getPrettyName());

element.dirty = this.dirty;
} catch (Exception e) {
// This should not happen
element = null;
Expand Down Expand Up @@ -417,7 +457,13 @@ public boolean apply(ElementInterface newElement, boolean clean)
*/
public void setOwnerDocument(XWikiDocument ownerDocument)
{
this.ownerDocument = ownerDocument;
if (this.ownerDocument != ownerDocument) {
this.ownerDocument = ownerDocument;

if (this.ownerDocument != null && isDirty()) {
this.ownerDocument.setMetaDataDirty(true);
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
*/
package com.xpn.xwiki.objects;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -44,7 +43,7 @@
import com.xpn.xwiki.objects.classes.PropertyClass;
import com.xpn.xwiki.web.Utils;

public class BaseObject extends BaseCollection<BaseObjectReference> implements ObjectInterface, Serializable, Cloneable
public class BaseObject extends BaseCollection<BaseObjectReference> implements ObjectInterface, Cloneable
{
private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -201,6 +200,8 @@ public BaseObject clone()
// is expensive)
object.setGuid(this.guid);

object.setDirty(isDirty());

return object;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
*/
package com.xpn.xwiki.objects;

import java.io.Serializable;
import java.util.Objects;

import org.apache.commons.lang3.ObjectUtils;
Expand All @@ -42,8 +41,7 @@
*/
// TODO: shouldn't this be abstract? toFormString and toText
// will never work unless getValue is overriden
public class BaseProperty<R extends EntityReference> extends BaseElement<R>
implements PropertyInterface, Serializable, Cloneable
public class BaseProperty<R extends EntityReference> extends BaseElement<R> implements PropertyInterface, Cloneable
{
private static final long serialVersionUID = 1L;

Expand All @@ -54,11 +52,6 @@ public class BaseProperty<R extends EntityReference> extends BaseElement<R>

private long id;

/**
* Set to true if value is not the same as the database value.
*/
private boolean isValueDirty = true;

@Override
protected R createReference()
{
Expand All @@ -82,6 +75,10 @@ public BaseCollection getObject()
public void setObject(BaseCollection object)
{
this.object = object;

if (this.object != null && isDirty()) {
this.object.setDirty(true);
}
}

@Override
Expand Down Expand Up @@ -124,9 +121,13 @@ public long getId()
@Override
public void setId(long id)
{
// I hate this.. needed for hibernate to find the object
// when loading the collections..
this.id = id;
if (id != this.id) {
// I hate this.. needed for hibernate to find the object
// when loading the collections..
this.id = id;

setDirty(true);
}
}

@Override
Expand Down Expand Up @@ -155,11 +156,12 @@ public BaseProperty<R> clone()

cloneInternal(property);

property.isValueDirty = this.isValueDirty;
property.ownerDocument = this.ownerDocument;

property.setObject(getObject());

property.setDirty(isDirty());

return property;
}

Expand Down Expand Up @@ -347,10 +349,12 @@ public boolean apply(ElementInterface newProperty, boolean clean)
/**
* @return {@literal true} if the property value doesn't match the value in the database.
* @since 4.3M2
* @deprecated use {@link #isDirty()} instead
*/
@Deprecated(since = "17.1.0RC1")
public boolean isValueDirty()
{
return this.isValueDirty;
return isDirty();
}

/**
Expand All @@ -360,38 +364,29 @@ public boolean isValueDirty()
*/
protected void setValueDirty(Object newValue)
{
if (!this.isValueDirty && !Objects.equals(newValue, getValue())) {
if (!isDirty() && !Objects.equals(newValue, getValue())) {
setValueDirty(true);
}
}

/**
* @param valueDirty Indicate if the dirty flag should be set or cleared.
* @since 4.3M2
* @deprecated use {@link #setDirty(boolean)} instead
*/
@Deprecated(since = "17.1.0RC1")
public void setValueDirty(boolean valueDirty)
{
this.isValueDirty = valueDirty;
if (valueDirty && this.ownerDocument != null) {
this.ownerDocument.setMetaDataDirty(true);
}
setDirty(valueDirty);
}

/**
* Set the owner document of this base property.
*
* @param ownerDocument The owner document.
* @since 4.3M2
*/
@Override
public void setOwnerDocument(XWikiDocument ownerDocument)
public void setDirty(boolean dirty)
{
if (this.ownerDocument != ownerDocument) {
super.setOwnerDocument(ownerDocument);
super.setDirty(dirty);

if (ownerDocument != null && this.isValueDirty) {
ownerDocument.setMetaDataDirty(true);
}
if (dirty && this.object != null) {
this.object.setDirty(true);
}
}

Expand Down
Loading

0 comments on commit 081a360

Please sign in to comment.