/** * Helper method to unset the specified ShardedEntity from the ShardedEntityContextHolder * * @param entity the ShardedEntity to unset from the ShardedEntityContextHolder * @throws PersistenceException in case the shard hint of specified ShardedEntity does not match * with the value of the entity held by ShardedEntityContextHolder */ private void unsetShardedEntityContextHolder(ShardedEntity entity) throws PersistenceException { // unset the ShardedEntity from the ShardedEntityContextHolder if the type is // ShardedPersistentEntity. Cleans up the context that was // populated earlier using the ShardedEntityContextHolder#setShardedPersistentEntity() call ShardedEntity contextEntity = ShardedEntityContextHolder.getShardedEntity(); if (contextEntity != null && !contextEntity.getShardHint().equals(((ShardedEntity) entity).getShardHint())) { throw new PersistenceException( "Shard hints do not match for the specified ShardedEntity instance and the one held in the context" + " Mismatched values are : " + contextEntity.getShardHint() + "," + ((ShardedEntity) entity).getShardHint()); } ShardedEntityContextHolder.clearShardedEntity(); }
/** * Helper method to set the first of specified Criteria instances into the * ShardedEntityContextHolder if it is of type ShardedEntity. Throws an exception if * shardedentities are mixed with non-sharded ones in the same call. Also checks to see if all the * ShardedEntity instances belong to the same shard i.e. {@link ShardedEntity#getShardHint()} * returns the same value. Throws a PersistenceException otherwise. This defensive check is done * to avoid indeterministic transaction boundary behavior when shards are mapped to multiple * database instances. when shards are mapped to multiple database instances. * * @param criteria the ShardedEntity instances, the first of which is to be set into the * ShardedEntityContextHolder if it is of type ShardedEntity * @throws PersistenceException in case the shard hints of specified ShardedEntity instances do * not match */ private void checkAndPopulateShardedEntityContextHolder(Criteria[] criteria) throws PersistenceException { if (criteria.length != 0) { // check to see if sharded and non-sharded entities are part of the same call ShardedEntity shardedEntity = null; Criteria nonShardedEntity = null; for (Criteria entity : criteria) { if (ShardedEntity.class.isAssignableFrom(entity.getClass())) { shardedEntity = (ShardedEntity) entity; } else { nonShardedEntity = entity; } } if (shardedEntity != null && nonShardedEntity != null) { throw new PersistenceException( "Attempt to use sharded and non-sharded criteria in the same call. " + "Mixed types are : " + shardedEntity.getClass().getName() + "," + nonShardedEntity.getClass().getName()); } Criteria firstEntity = criteria[0]; String shardHint = (ShardedEntity.class.isAssignableFrom(firstEntity.getClass())) ? ((ShardedEntity) firstEntity).getShardHint() : ShardedEntity.DEFAULT_SHARD; for (Criteria entity : criteria) { if (ShardedEntity.class.isAssignableFrom(entity.getClass())) { if (!((ShardedEntity) entity).getShardHint().equals(shardHint)) { throw new PersistenceException( "Shard hints do not match for the specified Criteria i.e. ShardedEntity instances." + " Mismatched values are : " + shardHint + "," + ((ShardedEntity) entity).getShardHint()); } } // Set the PersistentEntity into the ShardedEntityContextHolder if the type is // ShardedPersistentEntity. Will be used in Datasource resolution if (ShardedEntity.class.isAssignableFrom(firstEntity.getClass())) { ShardedEntityContextHolder.setShardedEntity((ShardedEntity) firstEntity); } } } }