public <S extends T> S save(S newInstance) throws DataAccessException;
- public T merge(T transientObject) throws DataAccessException;
+ public T merge(T transientEntity) throws DataAccessException;
+
+ /**
+ * Same as {@link #merge(CdmBase)} but with the possibility to fully remove
+ * further objects from the database during the same session.
+ * This may become necessary if these objects were deleted from the detached object graph
+ * and are not handled via Cascade.REMOVE or orphanRemoval.
+ */
+ public T merge(T transientEntity, Collection<CdmBase> removedObjects) throws DataAccessException;
/**
* This method allows for the possibility of returning the input transient
* This method returns the root merged transient entity as well as all newly merged
* persistent entities within the return object.
*
- * @param transientObject
+ * @param transientEntity
* @param returnTransientEntity
* @return transient or persistent object depending on the value of returnTransientEntity
* @throws DataAccessException
*/
- public MergeResult<T> merge(T transientObject, boolean returnTransientEntity) throws DataAccessException;
+ public MergeResult<T> merge(T transientEntity, boolean returnTransientEntity) throws DataAccessException;
/**
* Obtains the specified LockMode on the supplied object
* @throws NullPointerException
* @throws MergeException
*/
- public <T extends CdmBase> void merge(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException;
+ public <T extends CdmBase> void merge(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException;
/**
* Computes if cdmBase2 can be merged into cdmBase1. This is usually the case when both
* @throws NullPointerException
* @throws MergeException
*/
- public <T extends CdmBase> boolean isMergeable(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException;
+ public <T extends CdmBase> boolean isMergeable(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException;
/**
* Returns a list of matching persistent objects according to the match strategy
import eu.etaxonomy.cdm.model.permission.User;
import eu.etaxonomy.cdm.model.view.AuditEvent;
import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
+import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
import eu.etaxonomy.cdm.persistence.dao.common.Restriction.Operator;
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
extends DaoBase
implements ICdmEntityDao<T> {
- private static final Logger logger = LogManager.getLogger(CdmEntityDaoBase.class);
+ private static final Logger logger = LogManager.getLogger();
+
+ @Autowired
+ private ICdmGenericDao genericDao;
protected int flushAfterNo = 1000; // large numbers may cause synchronisation errors
- // when commiting the session
+ // when committing the session
protected Class<T> type;
@Autowired
return persistentObject;
}
+ @Override
+ public T merge(T transientEntity, Collection<CdmBase> detachedObjectsToRemove) throws DataAccessException{
+ T result = merge(transientEntity);
+ for (CdmBase detachedObject : detachedObjectsToRemove) {
+ CdmBase persistedObject = genericDao.find(CdmBase.deproxy(detachedObject.getClass()), detachedObject.getUuid());
+ if (persistedObject != null) {
+ genericDao.delete(persistedObject);
+ }
+ }
+ return result;
+ }
+
@Override
public UUID saveOrUpdate(T transientObject) throws DataAccessException {
if (transientObject == null) {
-/**\r
-* Copyright (C) 2009 EDIT\r
-* European Distributed Institute of Taxonomy\r
-* http://www.e-taxonomy.eu\r
-*\r
-* The contents of this file are subject to the Mozilla Public License Version 1.1\r
-* See LICENSE.TXT at the top of this package for the full license terms.\r
-*/\r
-package eu.etaxonomy.cdm.api.service;\r
-\r
-import java.util.UUID;\r
-\r
-import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;\r
-\r
-/**\r
- * @author a.kohlbecker\r
- * @since 24.03.2011\r
- *\r
- */\r
-public interface IPolytomousKeyNodeService extends IVersionableService<PolytomousKeyNode> {\r
-\r
- public DeleteResult delete(UUID nodeUuid, boolean deleteChildren);\r
-\r
-\r
-}\r
+/**
+* Copyright (C) 2009 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.api.service;
+
+import java.util.UUID;
+
+import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;
+
+/**
+ * @author a.kohlbecker
+ * @since 24.03.2011
+ */
+public interface IPolytomousKeyNodeService extends IVersionableService<PolytomousKeyNode> {
+
+ public DeleteResult delete(UUID nodeUuid, boolean deleteChildren);
+
+}
-/**\r
-* Copyright (C) 2009 EDIT\r
-* European Distributed Institute of Taxonomy\r
-* http://www.e-taxonomy.eu\r
-*\r
-* The contents of this file are subject to the Mozilla Public License Version 1.1\r
-* See LICENSE.TXT at the top of this package for the full license terms.\r
-*/\r
-\r
-package eu.etaxonomy.cdm.api.service;\r
-\r
-import java.util.List;\r
-import java.util.UUID;\r
-\r
-import eu.etaxonomy.cdm.api.service.pager.Pager;\r
-import eu.etaxonomy.cdm.model.description.PolytomousKey;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
-\r
-public interface IPolytomousKeyService extends IIdentifiableEntityService<PolytomousKey> {\r
-\r
- /**\r
- * Loads a polytomous key including all of its nodes (all the way down to the tips of the tree).\r
- * Because this method automatically adds key nodes recursively, adding "root" to property paths\r
- * is superfluous - the propertyPaths argument should be used to initialize property paths <i>in addition</i>\r
- * to the key nodes. The nodePaths argument is applied to each node in turn, so again, adding "children"\r
- * is also superfluous. The nodePaths argument should be used to specify additional properties of the\r
- * key node to initialize.\r
- *\r
- */\r
- public PolytomousKey loadWithNodes(UUID uuid, List<String> propertyPaths, List<String> nodePaths);\r
-\r
- public Pager<PolytomousKey> findByTaxonomicScope(TaxonBase taxon, Integer pageSize,\r
- Integer pageNumber, List<String> propertyPaths, List<String> nodePaths);\r
-\r
- /**\r
- * Refreshes all node numberings recursively from the root node downwards.\r
- *\r
- * @param polytomousKeyUuid\r
- * @return\r
- */\r
- public UpdateResult updateAllNodeNumberings(UUID polytomousKeyUuid);\r
-\r
- /**\r
- * Refreshes all node numberings for all polytomous keys recursively from the root node downwards.\r
- *\r
- * @return\r
- */\r
- public UpdateResult updateAllNodeNumberings();\r
-\r
-}\r
+/**
+* Copyright (C) 2009 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.cdm.api.service;
+
+import java.util.List;
+import java.util.UUID;
+
+import eu.etaxonomy.cdm.api.service.pager.Pager;
+import eu.etaxonomy.cdm.model.description.PolytomousKey;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+
+public interface IPolytomousKeyService extends IIdentifiableEntityService<PolytomousKey> {
+
+ /**
+ * Loads a polytomous key including all of its nodes (all the way down to the tips of the tree).
+ * Because this method automatically adds key nodes recursively, adding "root" to property paths
+ * is superfluous - the propertyPaths argument should be used to initialize property paths <i>in addition</i>
+ * to the key nodes. The nodePaths argument is applied to each node in turn, so again, adding "children"
+ * is also superfluous. The nodePaths argument should be used to specify additional properties of the
+ * key node to initialize.
+ *
+ */
+ public PolytomousKey loadWithNodes(UUID uuid, List<String> propertyPaths, List<String> nodePaths);
+
+ public Pager<PolytomousKey> findByTaxonomicScope(TaxonBase taxon, Integer pageSize,
+ Integer pageNumber, List<String> propertyPaths, List<String> nodePaths);
+
+ /**
+ * Refreshes all node numberings recursively from the root node downwards.
+ *
+ * @param polytomousKeyUuid
+ * @return
+ */
+ public UpdateResult updateAllNodeNumberings(UUID polytomousKeyUuid);
+
+ /**
+ * Refreshes all node numberings for all polytomous keys recursively from the root node downwards.
+ *
+ * @return
+ */
+ public UpdateResult updateAllNodeNumberings();
+
+}
import org.hibernate.event.spi.MergeEvent;
import eu.etaxonomy.cdm.api.service.pager.Pager;
+import eu.etaxonomy.cdm.model.common.CdmBase;
import eu.etaxonomy.cdm.model.common.ICdmBase;
import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
*/
public T merge(T detachedObject);
+ public T merge(T detachedObject, CdmBase... removedObjects);
+
/**
* Returns a paged list of entities of type <T> optionally restricted
* to objects belonging to a class that that extends <T>
* The contents of this file are subject to the Mozilla Public License Version 1.1
* See LICENSE.TXT at the top of this package for the full license terms.
*/
-
package eu.etaxonomy.cdm.api.service;
import java.util.ArrayList;
@Service
@Transactional(readOnly = false)
-public class PolytomousKeyServiceImpl extends IdentifiableServiceBase<PolytomousKey, IPolytomousKeyDao> implements IPolytomousKeyService {
+public class PolytomousKeyServiceImpl
+ extends IdentifiableServiceBase<PolytomousKey, IPolytomousKeyDao>
+ implements IPolytomousKeyService {
private IIdentificationKeyDao identificationKeyDao;
package eu.etaxonomy.cdm.api.service;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
return dao.merge(newInstance);
}
+ /**
+ * Same as #merge(T) but with the possibility to fully remove further entities
+ * from the database during the same session. This may become necessary if these
+ * entities were deleted from the detached object graph and are not handled
+ * via Cascade.REMOVE or orphanRemoval, e.g. when children were removed
+ * from its parents and not used elsewhere anymore.
+ */
+ @Override
+ public T merge(T detachedObject, CdmBase... removedObjects) {
+ return dao.merge(detachedObject, Arrays.asList(removedObjects));
+ }
+
@Override
@Transactional(readOnly = false)
public MergeResult<T> merge(T newInstance, boolean returnTransientEntity) {