Implement tilted relationships to help improve performance

This commit is contained in:
April Herron
2021-01-27 09:41:38 -05:00
parent 12ffc78452
commit 06c39ad750
18 changed files with 159 additions and 50 deletions

View File

@@ -146,6 +146,14 @@ public class InitializeEntities {
copyToRight = Boolean.valueOf(copyToRightNode.getTextContent()); copyToRight = Boolean.valueOf(copyToRightNode.getTextContent());
} }
Node tiltedNode = eElement.getElementsByTagName("tilted").item(0);
RelationshipType.Tilted tilted;
if (tiltedNode == null) {
tilted = RelationshipType.Tilted.NONE;
} else {
tilted = RelationshipType.Tilted.valueOf(tiltedNode.getTextContent().toUpperCase());
}
NodeList leftCardinalityList = eElement.getElementsByTagName("leftCardinality"); NodeList leftCardinalityList = eElement.getElementsByTagName("leftCardinality");
NodeList rightCardinalityList = eElement.getElementsByTagName("rightCardinality"); NodeList rightCardinalityList = eElement.getElementsByTagName("rightCardinality");
@@ -170,7 +178,8 @@ public class InitializeEntities {
} }
populateRelationshipType(context, leftType, rightType, leftwardType, rightwardType, populateRelationshipType(context, leftType, rightType, leftwardType, rightwardType,
leftCardinalityMin, leftCardinalityMax, leftCardinalityMin, leftCardinalityMax,
rightCardinalityMin, rightCardinalityMax, copyToLeft, copyToRight); rightCardinalityMin, rightCardinalityMax, copyToLeft, copyToRight,
tilted);
} }
@@ -190,7 +199,7 @@ public class InitializeEntities {
private void populateRelationshipType(Context context, String leftType, String rightType, String leftwardType, private void populateRelationshipType(Context context, String leftType, String rightType, String leftwardType,
String rightwardType, String leftCardinalityMin, String leftCardinalityMax, String rightwardType, String leftCardinalityMin, String leftCardinalityMax,
String rightCardinalityMin, String rightCardinalityMax, String rightCardinalityMin, String rightCardinalityMax,
Boolean copyToLeft, Boolean copyToRight) Boolean copyToLeft, Boolean copyToRight, RelationshipType.Tilted tilted)
throws SQLException, AuthorizeException { throws SQLException, AuthorizeException {
EntityType leftEntityType = entityTypeService.findByEntityType(context,leftType); EntityType leftEntityType = entityTypeService.findByEntityType(context,leftType);
@@ -231,10 +240,11 @@ public class InitializeEntities {
relationshipTypeService.create(context, leftEntityType, rightEntityType, leftwardType, rightwardType, relationshipTypeService.create(context, leftEntityType, rightEntityType, leftwardType, rightwardType,
leftCardinalityMinInteger, leftCardinalityMaxInteger, leftCardinalityMinInteger, leftCardinalityMaxInteger,
rightCardinalityMinInteger, rightCardinalityMaxInteger, rightCardinalityMinInteger, rightCardinalityMaxInteger,
copyToLeft, copyToRight); copyToLeft, copyToRight, tilted);
} else { } else {
relationshipType.setCopyToLeft(copyToLeft); relationshipType.setCopyToLeft(copyToLeft);
relationshipType.setCopyToRight(copyToRight); relationshipType.setCopyToRight(copyToRight);
relationshipType.setTilted(tilted);
relationshipType.setLeftMinCardinality(leftCardinalityMinInteger); relationshipType.setLeftMinCardinality(leftCardinalityMinInteger);
relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger); relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger);
relationshipType.setRightMinCardinality(rightCardinalityMinInteger); relationshipType.setRightMinCardinality(rightCardinalityMinInteger);

View File

@@ -44,7 +44,7 @@ public class EntityServiceImpl implements EntityService {
public Entity findByItemId(Context context, UUID itemId, Integer limit, Integer offset) throws SQLException { public Entity findByItemId(Context context, UUID itemId, Integer limit, Integer offset) throws SQLException {
Item item = itemService.find(context, itemId); Item item = itemService.find(context, itemId);
List<Relationship> relationshipList = relationshipService.findByItem(context, item, limit, offset); List<Relationship> relationshipList = relationshipService.findByItem(context, item, limit, offset, true);
return new Entity(item, relationshipList); return new Entity(item, relationshipList);
} }

View File

@@ -46,7 +46,7 @@ public class RelationshipMetadataServiceImpl implements RelationshipMetadataServ
try { try {
String entityType = getEntityTypeStringFromMetadata(item); String entityType = getEntityTypeStringFromMetadata(item);
if (StringUtils.isNotBlank(entityType)) { if (StringUtils.isNotBlank(entityType)) {
List<Relationship> relationships = relationshipService.findByItem(context, item); List<Relationship> relationships = relationshipService.findByItem(context, item, -1, -1, true);
for (Relationship relationship : relationships) { for (Relationship relationship : relationships) {
fullMetadataValueList fullMetadataValueList
.addAll(findRelationshipMetadataValueForItemRelationship(context, item, entityType, .addAll(findRelationshipMetadataValueForItemRelationship(context, item, entityType,

View File

@@ -268,15 +268,14 @@ public class RelationshipServiceImpl implements RelationshipService {
@Override @Override
public List<Relationship> findByItem(Context context, Item item) throws SQLException { public List<Relationship> findByItem(Context context, Item item) throws SQLException {
return findByItem(context, item, -1, -1, false);
return findByItem(context, item, -1, -1);
} }
@Override @Override
public List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset) public List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset,
throws SQLException { boolean excludeTilted) throws SQLException {
List<Relationship> list = relationshipDAO.findByItem(context, item, limit, offset); List<Relationship> list = relationshipDAO.findByItem(context, item, limit, offset, excludeTilted);
list.sort((o1, o2) -> { list.sort((o1, o2) -> {
int relationshipType = o1.getRelationshipType().getLeftwardType() int relationshipType = o1.getRelationshipType().getLeftwardType()

View File

@@ -113,6 +113,13 @@ public class RelationshipType implements ReloadableEntity<Integer> {
*/ */
@Column(name = "copy_to_right", nullable = false) @Column(name = "copy_to_right", nullable = false)
private boolean copyToRight; private boolean copyToRight;
/**
* The value indicating whether the relationship has more relationships on the right/left/neither.
*/
@Column(name = "tilted")
private Tilted tilted;
/** /**
* Protected constructor, create object using: * Protected constructor, create object using:
* {@link org.dspace.content.service.RelationshipTypeService#create(Context)} } * {@link org.dspace.content.service.RelationshipTypeService#create(Context)} }
@@ -287,6 +294,26 @@ public class RelationshipType implements ReloadableEntity<Integer> {
this.copyToRight = copyToRight; this.copyToRight = copyToRight;
} }
/**
* Generic getter for tilted
* @return the tilted value of this RelationshipType
*/
public Tilted getTilted() {
return tilted;
}
/**
* Generic setter for tilted
* @param tilted The tilted to be set on this RelationshipType
*/
public void setTilted(Tilted tilted) {
this.tilted = tilted;
}
public enum Tilted {
NONE, LEFT, RIGHT;
}
/** /**
* Standard getter for the ID of this RelationshipType * Standard getter for the ID of this RelationshipType
* @return The ID of this RelationshipType * @return The ID of this RelationshipType

View File

@@ -121,7 +121,8 @@ public class RelationshipTypeServiceImpl implements RelationshipTypeService {
public RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType, public RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType,
String leftwardType, String rightwardType, Integer leftCardinalityMinInteger, String leftwardType, String rightwardType, Integer leftCardinalityMinInteger,
Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger, Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger,
Integer rightCardinalityMaxInteger, Boolean copyToLeft, Boolean copyToRight) Integer rightCardinalityMaxInteger, Boolean copyToLeft, Boolean copyToRight,
RelationshipType.Tilted tilted)
throws SQLException, AuthorizeException { throws SQLException, AuthorizeException {
RelationshipType relationshipType = new RelationshipType(); RelationshipType relationshipType = new RelationshipType();
relationshipType.setLeftType(leftEntityType); relationshipType.setLeftType(leftEntityType);
@@ -130,6 +131,7 @@ public class RelationshipTypeServiceImpl implements RelationshipTypeService {
relationshipType.setRightwardType(rightwardType); relationshipType.setRightwardType(rightwardType);
relationshipType.setCopyToLeft(copyToLeft); relationshipType.setCopyToLeft(copyToLeft);
relationshipType.setCopyToRight(copyToRight); relationshipType.setCopyToRight(copyToRight);
relationshipType.setTilted(tilted);
relationshipType.setLeftMinCardinality(leftCardinalityMinInteger); relationshipType.setLeftMinCardinality(leftCardinalityMinInteger);
relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger); relationshipType.setLeftMaxCardinality(leftCardinalityMaxInteger);
relationshipType.setRightMinCardinality(rightCardinalityMinInteger); relationshipType.setRightMinCardinality(rightCardinalityMinInteger);

View File

@@ -27,28 +27,31 @@ public interface RelationshipDAO extends GenericDAO<Relationship> {
/** /**
* This method returns a list of Relationship objects that have the given Item object * This method returns a list of Relationship objects that have the given Item object
* as a leftItem or a rightItem * as a leftItem or a rightItem
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param item The item that should be either a leftItem or a rightItem of all * @param item The item that should be either a leftItem or a rightItem of all
* the Relationship objects in the returned list * the Relationship objects in the returned list
* @return The list of Relationship objects that contain either a left or a * @param excludeTilted If true, excludes tilted relationships
* right item that is equal to the given item * @return The list of Relationship objects that contain either a left or a
* @throws SQLException If something goes wrong * right item that is equal to the given item
* @throws SQLException If something goes wrong
*/ */
List<Relationship> findByItem(Context context, Item item) throws SQLException; List<Relationship> findByItem(Context context, Item item, boolean excludeTilted) throws SQLException;
/** /**
* This method returns a list of Relationship objects that have the given Item object * This method returns a list of Relationship objects that have the given Item object
* as a leftItem or a rightItem * as a leftItem or a rightItem
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param item The item that should be either a leftItem or a rightItem of all * @param item The item that should be either a leftItem or a rightItem of all
* the Relationship objects in the returned list * the Relationship objects in the returned list
* @param limit paging limit * @param limit paging limit
* @param offset paging offset * @param offset paging offset
* @return The list of Relationship objects that contain either a left or a * @param excludeTilted If true, excludes tilted relationships
* right item that is equal to the given item * @return The list of Relationship objects that contain either a left or a
* @throws SQLException If something goes wrong * right item that is equal to the given item
* @throws SQLException If something goes wrong
*/ */
List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset) throws SQLException; List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset, boolean excludeTilted)
throws SQLException;
/** /**
* This method returns the next leftplace integer to use for a relationship with this item as the leftItem * This method returns the next leftplace integer to use for a relationship with this item as the leftItem

View File

@@ -17,6 +17,7 @@ import javax.persistence.criteria.Root;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.Relationship; import org.dspace.content.Relationship;
import org.dspace.content.RelationshipType; import org.dspace.content.RelationshipType;
import org.dspace.content.RelationshipType_;
import org.dspace.content.Relationship_; import org.dspace.content.Relationship_;
import org.dspace.content.dao.RelationshipDAO; import org.dspace.content.dao.RelationshipDAO;
import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.factory.ContentServiceFactory;
@@ -27,22 +28,42 @@ import org.dspace.core.Context;
public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> implements RelationshipDAO { public class RelationshipDAOImpl extends AbstractHibernateDAO<Relationship> implements RelationshipDAO {
@Override @Override
public List<Relationship> findByItem(Context context, Item item) throws SQLException { public List<Relationship> findByItem(Context context, Item item, boolean excludeTilted) throws SQLException {
return findByItem(context, item, -1, -1, excludeTilted);
return findByItem(context, item, -1, -1);
} }
@Override @Override
public List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset) public List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset,
throws SQLException { boolean excludeTilted) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class); CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Relationship.class);
Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class); Root<Relationship> relationshipRoot = criteriaQuery.from(Relationship.class);
criteriaQuery.select(relationshipRoot); criteriaQuery.select(relationshipRoot);
criteriaQuery if (excludeTilted) {
.where(criteriaBuilder.or(criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item), criteriaQuery
criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item))); .where(criteriaBuilder.or(
criteriaBuilder.and(
criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item),
criteriaBuilder.or(
criteriaBuilder.isNull(relationshipRoot.get(Relationship_.relationshipType)
.get(RelationshipType_.tilted)),
criteriaBuilder.notEqual(relationshipRoot
.get(Relationship_.relationshipType)
.get(RelationshipType_.tilted), RelationshipType.Tilted.RIGHT))),
criteriaBuilder.and(
criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item),
criteriaBuilder.or(
criteriaBuilder.isNull(relationshipRoot.get(Relationship_.relationshipType)
.get(RelationshipType_.tilted)),
criteriaBuilder.notEqual(relationshipRoot
.get(Relationship_.relationshipType)
.get(RelationshipType_.tilted), RelationshipType.Tilted.LEFT)))));
} else {
criteriaQuery
.where(criteriaBuilder.or(criteriaBuilder.equal(relationshipRoot.get(Relationship_.leftItem), item),
criteriaBuilder.equal(relationshipRoot.get(Relationship_.rightItem), item)));
}
return list(context, criteriaQuery, false, Relationship.class, limit, offset); return list(context, criteriaQuery, false, Relationship.class, limit, offset);
} }

View File

@@ -35,14 +35,18 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
/** /**
* Retrieves the list of Relationships currently in the system for which the given Item is either * Retrieves the list of Relationships currently in the system for which the given Item is either
* a leftItem or a rightItem object * a leftItem or a rightItem object
* @param context The relevant DSpace context * @param context The relevant DSpace context
* @param item The Item that has to be the left or right item for the relationship to be included in the list * @param item The Item that has to be the left or right item for the relationship to be
* @param limit paging limit * included in the list
* @param offset paging offset * @param limit paging limit
* @return The list of relationships for which each relationship adheres to the above listed constraint * @param offset paging offset
* @throws SQLException If something goes wrong * @param excludeTilted If true, excludes tilted relationships
* @return The list of relationships for which each relationship adheres to the above
* listed constraint
* @throws SQLException If something goes wrong
*/ */
List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset) throws SQLException; List<Relationship> findByItem(Context context, Item item, Integer limit, Integer offset, boolean excludeTilted)
throws SQLException;
/** /**
* Retrieves the full list of relationships currently in the system * Retrieves the full list of relationships currently in the system
@@ -317,4 +321,4 @@ public interface RelationshipService extends DSpaceCRUDService<Relationship> {
*/ */
void delete(Context context, Relationship relationship, boolean copyToLeftItem, boolean copyToRightItem) void delete(Context context, Relationship relationship, boolean copyToLeftItem, boolean copyToRightItem)
throws SQLException, AuthorizeException; throws SQLException, AuthorizeException;
} }

View File

@@ -174,6 +174,7 @@ public interface RelationshipTypeService extends DSpaceCRUDService<RelationshipT
RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType, RelationshipType create(Context context, EntityType leftEntityType, EntityType rightEntityType,
String leftwardType, String rightwardType, Integer leftCardinalityMinInteger, String leftwardType, String rightwardType, Integer leftCardinalityMinInteger,
Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger, Integer leftCardinalityMaxInteger, Integer rightCardinalityMinInteger,
Integer rightCardinalityMaxInteger, Boolean copyToLeft, Boolean copyToRight) Integer rightCardinalityMaxInteger, Boolean copyToLeft, Boolean copyToRight,
RelationshipType.Tilted tilted)
throws SQLException, AuthorizeException; throws SQLException, AuthorizeException;
} }

View File

@@ -0,0 +1,13 @@
--
-- The contents of this file are subject to the license and copyright
-- detailed in the LICENSE and NOTICE files at the root of the source
-- tree and available online at
--
-- http://www.dspace.org/license/
--
-----------------------------------------------------------------------------------
-- Create columns copy_left and copy_right for RelationshipType
-----------------------------------------------------------------------------------
ALTER TABLE relationship_type ADD tilted INTEGER;

View File

@@ -0,0 +1,13 @@
--
-- The contents of this file are subject to the license and copyright
-- detailed in the LICENSE and NOTICE files at the root of the source
-- tree and available online at
--
-- http://www.dspace.org/license/
--
-----------------------------------------------------------------------------------
-- Create columns copy_left and copy_right for RelationshipType
-----------------------------------------------------------------------------------
ALTER TABLE relationship_type ADD tilted INTEGER;

View File

@@ -0,0 +1,13 @@
--
-- The contents of this file are subject to the license and copyright
-- detailed in the LICENSE and NOTICE files at the root of the source
-- tree and available online at
--
-- http://www.dspace.org/license/
--
-----------------------------------------------------------------------------------
-- Create columns copy_left and copy_right for RelationshipType
-----------------------------------------------------------------------------------
ALTER TABLE relationship_type ADD tilted INTEGER;

View File

@@ -2,13 +2,14 @@
<!ELEMENT relationships (type)*> <!ELEMENT relationships (type)*>
<!ELEMENT type (leftType|rightType|leftwardType|rightwardType|leftCardinality|rightCardinality|copyToLeft|copyToRight)*> <!ELEMENT type (leftType|rightType|leftwardType|rightwardType|leftCardinality|rightCardinality|copyToLeft|copyToRight|tilted)*>
<!ELEMENT leftType (#PCDATA)> <!ELEMENT leftType (#PCDATA)>
<!ELEMENT rightType (#PCDATA)> <!ELEMENT rightType (#PCDATA)>
<!ELEMENT leftwardType (#PCDATA)> <!ELEMENT leftwardType (#PCDATA)>
<!ELEMENT rightwardType (#PCDATA)> <!ELEMENT rightwardType (#PCDATA)>
<!ELEMENT copyToLeft (#PCDATA)> <!ELEMENT copyToLeft (#PCDATA)>
<!ELEMENT copyToRight (#PCDATA)> <!ELEMENT copyToRight (#PCDATA)>
<!ELEMENT tilted (#PCDATA)>
<!ELEMENT leftCardinality (min|max)*> <!ELEMENT leftCardinality (min|max)*>
<!ELEMENT min (#PCDATA)> <!ELEMENT min (#PCDATA)>
<!ELEMENT rightCardinality (min|max)*> <!ELEMENT rightCardinality (min|max)*>

View File

@@ -110,10 +110,10 @@ public class RelationshipServiceImplTest {
relationshipTest.add(getRelationship(cindy, hank, hasFather,0,0)); relationshipTest.add(getRelationship(cindy, hank, hasFather,0,0));
relationshipTest.add(getRelationship(fred, cindy, hasMother,0,0)); relationshipTest.add(getRelationship(fred, cindy, hasMother,0,0));
relationshipTest.add(getRelationship(bob, cindy, hasMother,1,0)); relationshipTest.add(getRelationship(bob, cindy, hasMother,1,0));
when(relationshipService.findByItem(context, cindy, -1, -1)).thenReturn(relationshipTest); when(relationshipService.findByItem(context, cindy, -1, -1, false)).thenReturn(relationshipTest);
// Mock the state of objects utilized in findByItem() to meet the success criteria of the invocation // Mock the state of objects utilized in findByItem() to meet the success criteria of the invocation
when(relationshipDAO.findByItem(context, cindy, -1, -1)).thenReturn(relationshipTest); when(relationshipDAO.findByItem(context, cindy, -1, -1, false)).thenReturn(relationshipTest);
List<Relationship> results = relationshipService.findByItem(context, cindy); List<Relationship> results = relationshipService.findByItem(context, cindy);
assertEquals("TestFindByItem 0", relationshipTest, results); assertEquals("TestFindByItem 0", relationshipTest, results);

View File

@@ -134,7 +134,8 @@ public class RelationshipDAOImplTest extends AbstractIntegrationTest {
*/ */
@Test @Test
public void testFindByItem() throws Exception { public void testFindByItem() throws Exception {
assertEquals("TestFindByItem 0", relationshipsList, relationshipService.findByItem(context, itemOne, -1, -1)); assertEquals("TestFindByItem 0", relationshipsList, relationshipService.findByItem(context, itemOne,
-1, -1, false));
} }
/** /**

View File

@@ -55,7 +55,7 @@ public class ItemRelationshipLinkRepository extends AbstractDSpaceRestRepository
int total = relationshipService.countByItem(context, item); int total = relationshipService.countByItem(context, item);
Pageable pageable = utils.getPageable(optionalPageable); Pageable pageable = utils.getPageable(optionalPageable);
List<Relationship> relationships = relationshipService.findByItem(context, item, List<Relationship> relationships = relationshipService.findByItem(context, item,
pageable.getPageSize(), Math.toIntExact(pageable.getOffset())); pageable.getPageSize(), Math.toIntExact(pageable.getOffset()), true);
return converter.toRestPage(relationships, pageable, total, projection); return converter.toRestPage(relationships, pageable, total, projection);
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View File

@@ -2,13 +2,14 @@
<!ELEMENT relationships (type)*> <!ELEMENT relationships (type)*>
<!ELEMENT type (leftType|rightType|leftwardType|rightwardType|leftCardinality|rightCardinality|copyToLeft|copyToRight)*> <!ELEMENT type (leftType|rightType|leftwardType|rightwardType|leftCardinality|rightCardinality|copyToLeft|copyToRight|tilted)*>
<!ELEMENT leftType (#PCDATA)> <!ELEMENT leftType (#PCDATA)>
<!ELEMENT rightType (#PCDATA)> <!ELEMENT rightType (#PCDATA)>
<!ELEMENT leftwardType (#PCDATA)> <!ELEMENT leftwardType (#PCDATA)>
<!ELEMENT rightwardType (#PCDATA)> <!ELEMENT rightwardType (#PCDATA)>
<!ELEMENT copyToLeft (#PCDATA)> <!ELEMENT copyToLeft (#PCDATA)>
<!ELEMENT copyToRight (#PCDATA)> <!ELEMENT copyToRight (#PCDATA)>
<!ELEMENT tilted (#PCDATA)>
<!ELEMENT leftCardinality (min|max)*> <!ELEMENT leftCardinality (min|max)*>
<!ELEMENT min (#PCDATA)> <!ELEMENT min (#PCDATA)>
<!ELEMENT rightCardinality (min|max)*> <!ELEMENT rightCardinality (min|max)*>