Skip to content
This repository has been archived by the owner on Jul 11, 2022. It is now read-only.

Commit

Permalink
In a recent commit for [1120417] (and the resulting oracle test failu…
Browse files Browse the repository at this point in the history
…res) we

added protection against Hibernate errors related  to detached sets when
orphanRemoval=true.  This applies similar changes to entity classes
outside of the BZ work.

(cherry picked from commit 0e8b7ed)
Signed-off-by: Jay Shaughnessy <jshaughn@redhat.com>
  • Loading branch information
jshaughn committed Sep 26, 2014
1 parent e301dd8 commit e9498be
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 35 deletions.
Expand Up @@ -390,8 +390,8 @@ public Configuration build() {
// use the prop name as the map key
@MapKey(name = "name")
// CascadeType.REMOVE has been omitted, the cascade delete has been moved to the data model for performance
@Cascade({ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@OneToMany(mappedBy = "configuration", fetch = FetchType.EAGER)
@Cascade({ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
@OneToMany(mappedBy = "configuration", fetch = FetchType.EAGER, orphanRemoval = true)
@XmlTransient
private Map<String, Property> properties = new LinkedHashMap<String, Property>(1);

Expand Down Expand Up @@ -771,6 +771,8 @@ public void setProperties(Collection<Property> properties) {
return;
}

// Don't replace the possible Hibernate proxy when orphanRemoval=true. It can cause
// "collection with cascade=all-delete-orphan was no longer referenced" exceptions.
this.properties.clear();
for (Property p : properties) {
this.put(p);
Expand Down Expand Up @@ -866,6 +868,10 @@ public void cleanoutRawConfiguration() {
}
}

/**
* Warning: This should probably not be performed on an attached entity, it could replace a
* Hibernate proxy, which can lead to issues (especially when orphanRemoval=true)
*/
public void resize() {
Map<String,Property> tmp =new LinkedHashMap<String, Property>(this.properties.size());
tmp.putAll(this.properties);
Expand Down
Expand Up @@ -59,9 +59,9 @@
public class PropertyList extends Property {
private static final long serialVersionUID = 1L;

// CascadeType.REMOVE has been omitted, the cascade delete has been moved to the data model for performance
@Cascade( { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@OneToMany(mappedBy = "parentList", targetEntity = Property.class, fetch = FetchType.EAGER)
// CascadeType.REMOVE has been omitted, the cascade delete has been moved to the data model for performance
@Cascade({ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
@OneToMany(mappedBy = "parentList", targetEntity = Property.class, fetch = FetchType.EAGER, orphanRemoval = true)
// Order by primary key which will also put the list elements in chronological order.
// Note, if we decide at some point to add support in the GUI for reordering list elements, we'll
// need to add a new ORDER column and order by that.
Expand Down
Expand Up @@ -60,9 +60,9 @@ public class PropertyMap extends Property implements AbstractPropertyMap {

// use the prop name as the map key
@MapKey(name = "name")
// CascadeType.REMOVE has been omitted, the cascade delete has been moved to the data model for performance
@Cascade({ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@OneToMany(mappedBy = "parentMap", fetch = FetchType.EAGER)
// CascadeType.REMOVE has been omitted, the cascade delete has been moved to the data model for performance
@Cascade({ CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
@OneToMany(mappedBy = "parentMap", fetch = FetchType.EAGER, orphanRemoval = true)
private Map<String, Property> map = new LinkedHashMap<String, Property>();

/**
Expand All @@ -80,7 +80,8 @@ protected PropertyMap(PropertyMap original, boolean keepId) {
*
* @param name the name of the map itself
*/
public PropertyMap(@NotNull String name) {
public PropertyMap(@NotNull
String name) {
setName(name);
}

Expand All @@ -92,7 +93,8 @@ public PropertyMap(@NotNull String name) {
* @param name the name of the map itself
* @param startingProperties a set of properties to be immediately added to this map
*/
public PropertyMap(@NotNull String name, Property... startingProperties) {
public PropertyMap(@NotNull
String name, Property... startingProperties) {
this(name);
for (Property property : startingProperties) {
put(property);
Expand All @@ -118,17 +120,21 @@ public Map<String, Property> getMap() {
}

/**
* Sets the map of child properties directly to the given <code>map</code> reference. This means the actual <code>
* map</code> object is stored internally in this object. Changes made to <code>map</code> will be reflected back
* into this object.
* This clears the current internal map replaces it with all of the provided map entries.
*
* <p><b>Warning:</b> Caution should be used when setting this object's internal map. Please see
* {@link PropertyMap the javadoc for this class} for more information.</p>
*
* @param map the new map used internally by this object
* @param map the map providing the new mappings
*/
public void setMap(Map<String, Property> map) {
this.map = map;
if (this.map == map) {
return;
}
// Don't replace the possible Hibernate proxy when orphanRemoval=true. It can cause
// "collection with cascade=all-delete-orphan was no longer referenced" exceptions.
this.map = getMap();
this.map.clear();
if (null != map) {
this.map.putAll(map);
}
}

/**
Expand All @@ -137,7 +143,8 @@ public void setMap(Map<String, Property> map) {
*
* @param property the property to add to this map.
*/
public void put(@NotNull Property property) {
public void put(@NotNull
Property property) {
getMap().put(property.getName(), property);
property.setParentMap(this);
}
Expand Down
Expand Up @@ -97,8 +97,7 @@ public class ConfigurationDefinition implements Serializable {
// plugin descriptor, iterating on the map (LinkedHashMap) will give us the same ordering. So, unless
// propDef.order is set and used for ordering by the accessing code, we'll default to the descriptor order.
@OrderBy
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
@OneToMany(mappedBy = "configurationDefinition", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@OneToMany(mappedBy = "configurationDefinition", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Map<String, PropertyDefinition> propertyDefinitions = new LinkedHashMap<String, PropertyDefinition>();

// use the configTemplate name as the map key
Expand All @@ -117,7 +116,8 @@ protected ConfigurationDefinition() {
// JPA use only
}

public ConfigurationDefinition(@NotNull String name, String description) {
public ConfigurationDefinition(@NotNull
String name, String description) {
this.name = name.intern();
this.description = description;
}
Expand All @@ -135,9 +135,10 @@ public String getName() {
return name;
}

public void setName(@NotNull String name) {
public void setName(@NotNull
String name) {
// Need to protect due to possible deserialization from Coregui.
if (name!=null) {
if (name != null) {
this.name = name.intern();
} else {
this.name = null;
Expand Down Expand Up @@ -187,7 +188,16 @@ public Map<String, PropertyDefinition> getPropertyDefinitions() {
}

public void setPropertyDefinitions(Map<String, PropertyDefinition> propertyDefinitions) {
this.propertyDefinitions = propertyDefinitions;
if (this.propertyDefinitions == propertyDefinitions) {
return;
}
// Don't replace the possible Hibernate proxy when orphanRemoval=true. It can cause
// "collection with cascade=all-delete-orphan was no longer referenced" exceptions.
this.propertyDefinitions = getPropertyDefinitions();
this.propertyDefinitions.clear();
if (null != propertyDefinitions) {
this.propertyDefinitions.putAll(propertyDefinitions);
}
}

public void put(PropertyDefinition propertyDefinition) {
Expand Down Expand Up @@ -332,7 +342,8 @@ public ConfigurationTemplate getDefaultTemplate() {
* @return <code>ConfigurationTemplate</code> with the specified name; <code>null</code> if no template by that name
* exists.
*/
public ConfigurationTemplate getTemplate(@NotNull String name) {
public ConfigurationTemplate getTemplate(@NotNull
String name) {
return getTemplates().get(name);
}

Expand Down
Expand Up @@ -104,9 +104,8 @@ public class Dashboard implements Serializable {
@ManyToOne(fetch = FetchType.LAZY, optional = true)
private ResourceGroup group;

@OneToMany(mappedBy = "dashboard", fetch = FetchType.EAGER)
@Cascade( { org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.MERGE,
org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
@OneToMany(mappedBy = "dashboard", fetch = FetchType.EAGER, orphanRemoval = true)
@Cascade({ org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.MERGE })
private Set<DashboardPortlet> portlets = new HashSet<DashboardPortlet>();

public static final String CFG_COLUMNS = "columns";
Expand Down Expand Up @@ -251,10 +250,10 @@ public boolean removePortlet(DashboardPortlet storedPortlet) {
return true;
}

/**
/**
* This can be used to safely add a portlet without knowing the current portlet positioning on the
* Dashboard. It adds the portlet to the bottom of column with the least portlets.
*
*
* @param storedPortlet MODIFIED with assigned column, index
*/
public void addPortlet(DashboardPortlet storedPortlet) {
Expand All @@ -279,7 +278,7 @@ public void addPortlet(DashboardPortlet storedPortlet) {

/**
* Call this only if you are sure the column and index are valid, not already used and not leaving gaps.
*
*
* @param storedPortlet MODIFIED with assigned column, index
* @param column
* @param index
Expand Down
Expand Up @@ -1170,8 +1170,7 @@ public class Resource implements Comparable<Resource>, Serializable {
@OneToMany(mappedBy = "resource", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<Dashboard> dashboards = null;

@OneToMany(mappedBy = "resource", fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
@OneToMany(mappedBy = "resource", fetch = FetchType.LAZY, cascade = { CascadeType.ALL }, orphanRemoval = true)
private Set<DriftDefinition> driftDefinitions = null;

@Transient
Expand Down Expand Up @@ -1961,7 +1960,18 @@ public Set<DriftDefinition> getDriftDefinitions() {
}

public void setDriftDefinitions(Set<DriftDefinition> driftDefinitions) {
this.driftDefinitions = driftDefinitions;
if (this.driftDefinitions == driftDefinitions) {
return;
}
// Don't replace the possible Hibernate proxy when orphanRemoval=true. It can cause
// "collection with cascade=all-delete-orphan was no longer referenced" exceptions.
this.driftDefinitions = getDriftDefinitions();
this.driftDefinitions.clear();
if (null != driftDefinitions) {
for (DriftDefinition dd : driftDefinitions) {
addDriftDefinition(dd);
}
}
}

public void addDriftDefinition(DriftDefinition driftDefinition) {
Expand Down

0 comments on commit e9498be

Please sign in to comment.