diff --git a/source/java/org/alfresco/repo/domain/DbAccessControlList.java b/source/java/org/alfresco/repo/domain/DbAccessControlList.java index dad02839a7..c815337253 100644 --- a/source/java/org/alfresco/repo/domain/DbAccessControlList.java +++ b/source/java/org/alfresco/repo/domain/DbAccessControlList.java @@ -30,10 +30,6 @@ public interface DbAccessControlList { public long getId(); - public Node getNode(); - - public void setNode(Node node); - /** * * @return Returns the access control entries for this access control list diff --git a/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlListImpl.java b/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlListImpl.java index 4fa4f1725e..d761e6a5dd 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlListImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/DbAccessControlListImpl.java @@ -26,8 +26,6 @@ import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.DbAuthority; import org.alfresco.repo.domain.DbPermission; import org.alfresco.repo.domain.DbPermissionKey; -import org.alfresco.repo.domain.Node; -import org.alfresco.util.EqualsHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Session; @@ -42,7 +40,6 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces private static Log logger = LogFactory.getLog(DbAccessControlListImpl.class); private long id; - private Node node; private Set entries; private boolean inherits; @@ -57,7 +54,6 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces StringBuilder sb = new StringBuilder(128); sb.append("DbAccessControlListImpl") .append("[ id=").append(id) - .append(", node=").append(node) .append(", entries=").append(entries.size()) .append(", inherits=").append(inherits) .append("]"); @@ -77,14 +73,13 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces } DbAccessControlList other = (DbAccessControlList) o; - return (this.inherits == other.getInherits()) - && (EqualsHelper.nullSafeEquals(this.node, other.getNode())); + return (this.inherits == other.getInherits()); } @Override public int hashCode() { - return (node == null ? 0 : node.hashCode()); + return (inherits == false ? 0 : 17); } public long getId() @@ -101,16 +96,6 @@ public class DbAccessControlListImpl extends LifecycleAdapter implements DbAcces this.id = id; } - public Node getNode() - { - return node; - } - - public void setNode(Node node) - { - this.node = node; - } - public Set getEntries() { return entries; diff --git a/source/java/org/alfresco/repo/domain/hibernate/HibernateNodeTest.java b/source/java/org/alfresco/repo/domain/hibernate/HibernateNodeTest.java index f291218312..f4a8e650c1 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/HibernateNodeTest.java +++ b/source/java/org/alfresco/repo/domain/hibernate/HibernateNodeTest.java @@ -28,6 +28,7 @@ import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.repo.domain.ChildAssoc; +import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.Node; import org.alfresco.repo.domain.NodeAssoc; import org.alfresco.repo.domain.NodeKey; @@ -35,12 +36,14 @@ import org.alfresco.repo.domain.NodeStatus; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.domain.Store; import org.alfresco.repo.domain.StoreKey; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.BaseSpringTest; import org.alfresco.util.GUID; +import org.hibernate.CacheMode; import org.hibernate.exception.ConstraintViolationException; /** @@ -385,6 +388,133 @@ public class HibernateNodeTest extends BaseSpringTest { txn.rollback(); } + } + + /** + * Create some simple parent-child relationships and flush them. Then read them back in without + * using the L2 cache. + */ + public void testQueryJoins() throws Exception + { + getSession().setCacheMode(CacheMode.IGNORE); + // make a container node + Node containerNode = new NodeImpl(); + containerNode.setStore(store); + containerNode.setUuid(GUID.generate()); + containerNode.setTypeQName(ContentModel.TYPE_CONTAINER); + containerNode.getProperties().put(ContentModel.PROP_AUTHOR, new PropertyValue(DataTypeDefinition.TEXT, "ABC")); + containerNode.getProperties().put(ContentModel.PROP_ARCHIVED_BY, new PropertyValue(DataTypeDefinition.TEXT, "ABC")); + containerNode.getAspects().add(ContentModel.ASPECT_AUDITABLE); + Serializable containerNodeId = getSession().save(containerNode); + NodeKey containerNodeKey = new NodeKey(containerNode.getNodeRef()); + NodeStatus containerNodeStatus = new NodeStatusImpl(); + containerNodeStatus.setKey(containerNodeKey); + containerNodeStatus.setNode(containerNode); + containerNodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId()); + getSession().save(containerNodeStatus); + // make content node 1 + Node contentNode1 = new NodeImpl(); + contentNode1.setStore(store); + contentNode1.setUuid(GUID.generate()); + contentNode1.setTypeQName(ContentModel.TYPE_CONTENT); + contentNode1.getProperties().put(ContentModel.PROP_AUTHOR, new PropertyValue(DataTypeDefinition.TEXT, "ABC")); + contentNode1.getProperties().put(ContentModel.PROP_ARCHIVED_BY, new PropertyValue(DataTypeDefinition.TEXT, "ABC")); + contentNode1.getAspects().add(ContentModel.ASPECT_AUDITABLE); + Serializable contentNode1Id = getSession().save(contentNode1); + NodeKey contentNodeKey1 = new NodeKey(contentNode1.getNodeRef()); + NodeStatus contentNodeStatus1 = new NodeStatusImpl(); + contentNodeStatus1.setKey(contentNodeKey1); + contentNodeStatus1.setNode(contentNode1); + contentNodeStatus1.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId()); + getSession().save(contentNodeStatus1); + // make content node 2 + Node contentNode2 = new NodeImpl(); + contentNode2.setStore(store); + contentNode2.setUuid(GUID.generate()); + contentNode2.setTypeQName(ContentModel.TYPE_CONTENT); + Serializable contentNode2Id = getSession().save(contentNode2); + contentNode2.getProperties().put(ContentModel.PROP_AUTHOR, new PropertyValue(DataTypeDefinition.TEXT, "ABC")); + contentNode2.getProperties().put(ContentModel.PROP_ARCHIVED_BY, new PropertyValue(DataTypeDefinition.TEXT, "ABC")); + contentNode2.getAspects().add(ContentModel.ASPECT_AUDITABLE); + NodeKey contentNodeKey2 = new NodeKey(contentNode2.getNodeRef()); + NodeStatus contentNodeStatus2 = new NodeStatusImpl(); + contentNodeStatus2.setKey(contentNodeKey2); + contentNodeStatus2.setNode(contentNode2); + contentNodeStatus2.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId()); + getSession().save(contentNodeStatus2); + // create an association to content 1 + ChildAssoc assoc1 = new ChildAssocImpl(); + assoc1.setIsPrimary(true); + assoc1.setTypeQName(QName.createQName(null, "type1")); + assoc1.setQname(QName.createQName(null, "number1")); + assoc1.buildAssociation(containerNode, contentNode1); + getSession().save(assoc1); + // create an association to content 2 + ChildAssoc assoc2 = new ChildAssocImpl(); + assoc2.setIsPrimary(true); + assoc2.setTypeQName(QName.createQName(null, "type2")); + assoc2.setQname(QName.createQName(null, "number2")); + assoc2.buildAssociation(containerNode, contentNode2); + getSession().save(assoc2); + + // make sure that there are no entities cached in either L1 or L2 + getSession().flush(); + getSession().clear(); + + // now read the structure back in from the container down + containerNodeStatus = (NodeStatus) getSession().get(NodeStatusImpl.class, containerNodeKey); + containerNode = containerNodeStatus.getNode(); + Collection assocs = containerNode.getChildAssocs(); + for (ChildAssoc assoc : assocs) + { + Node childNode = assoc.getChild(); + Store store = childNode.getStore(); + childNode.getAspects().size(); + childNode.getProperties().size(); + childNode.getParentAssocs().size(); + childNode.getChildAssocs().size(); + childNode.getSourceNodeAssocs().size(); + childNode.getTargetNodeAssocs().size(); + DbAccessControlList acl = childNode.getAccessControlList(); + if (acl != null) + { + acl.getEntries().size(); + } + } + + // clear out again + getSession().clear(); + + // now remove a property from each child + containerNodeStatus = (NodeStatus) getSession().get(NodeStatusImpl.class, containerNodeKey); + containerNode = containerNodeStatus.getNode(); + assocs = containerNode.getChildAssocs(); + for (ChildAssoc assoc : assocs) + { + Node childNode = assoc.getChild(); + PropertyValue removed = childNode.getProperties().remove(ContentModel.PROP_ARCHIVED_BY); + assertNotNull("Property was not present", removed); + } + // expect that just the specific property gets removed in the delete statement + getSession().flush(); + getSession().clear(); + + // Create a second association to content 2 + // create an association to content 2 + containerNodeStatus = (NodeStatus) getSession().get(NodeStatusImpl.class, containerNodeKey); + containerNode = containerNodeStatus.getNode(); + contentNodeStatus2 = (NodeStatus) getSession().get(NodeStatusImpl.class, contentNodeKey2); + contentNode2 = contentNodeStatus2.getNode(); + ChildAssoc assoc3 = new ChildAssocImpl(); + assoc3.setIsPrimary(false); + assoc3.setTypeQName(QName.createQName(null, "type3")); + assoc3.setQname(QName.createQName(null, "number3")); + assoc3.buildAssociation(containerNode, contentNode2); // check whether the children are pulled in for this + getSession().save(assoc3); + + // flush it + getSession().flush(); + getSession().clear(); } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml index 6c7b1d4f58..c832657637 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml @@ -38,14 +38,16 @@ - - + + unique="false" + not-null="false" + cascade="delete" /> @@ -98,8 +100,8 @@ @@ -173,8 +175,8 @@ @@ -182,8 +184,8 @@ diff --git a/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml index 9d72a4fe85..8c0490ff4a 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Permission.hbm.xml @@ -19,14 +19,6 @@ - - - - emptySet()); + return snpe; + } + else + { + Set entries = acl.getEntries(); + SimpleNodePermissionEntry snpe = new SimpleNodePermissionEntry( + node.getNodeRef(), + acl.getInherits(), + createSimplePermissionEntries(node, entries)); + return snpe; } - Set entries = acl.getEntries(); - SimpleNodePermissionEntry snpe = new SimpleNodePermissionEntry( - acl.getNode().getNodeRef(), - acl.getInherits(), - createSimplePermissionEntries(entries)); - return snpe; } /** * @param entries access control entries * @return Returns a unique set of entries that can be given back to the outside world */ - private Set createSimplePermissionEntries(Collection entries) + private Set createSimplePermissionEntries(Node node, Collection entries) { if (entries == null) { @@ -481,20 +488,20 @@ public class PermissionsDaoComponentImpl extends HibernateDaoSupport implements { for (DbAccessControlEntry entry : entries) { - spes.add(createSimplePermissionEntry(entry)); + spes.add(createSimplePermissionEntry(node, entry)); } } return spes; } - private static SimplePermissionEntry createSimplePermissionEntry(DbAccessControlEntry ace) + private static SimplePermissionEntry createSimplePermissionEntry(Node node, DbAccessControlEntry ace) { if (ace == null) { return null; } return new SimplePermissionEntry( - ace.getAccessControlList().getNode().getNodeRef(), + node.getNodeRef(), createSimplePermissionReference(ace.getPermission()), ace.getAuthority().getRecipient(), ace.isAllowed() ? AccessStatus.ALLOWED : AccessStatus.DENIED);