Class UpdateExecutor
java.lang.Object
org.broadleafcommerce.common.util.UpdateExecutor
The purpose for this class is to provide an alternate approach to an HQL UPDATE query for batch updates on Hibernate filtered
entities (such as sandboxable and multi-tenant entities).
This class takes an interesting approach to the use of update queries. To explain, a bit of background is required.
First, Hibernate will create a temporary table and fill it will ids to use in a where clause when it executs an HQL UPDATE
query. However, it will only create this temporary table when the target entity has Hibernate filters applied
(i.e. sandboxable or multi-tenant entities). When creating this temporary table, a ‘insert into select’ is used to
populate the values. It is my understanding that this ends up creating some locks on the original table. Because of
these locks, we were seeing some instances of deadlocks during concurrent admin usage. The key was to avoid
the temporary table creation. We did this by first selecting for ids (so that the filters were still honored) and then
using a simple, native sql statement to execute the update on entities matching those ids. The native sql needs to be basic
enough that it’s portable across platforms.
This class is responsible for building the native sql based on a template String. It does it in a way using a standard
parameterized query (rather than string concatenation) to avoid the possibility of any sql injection exploit.
This implementation has the added benefit of breaking up large IN clauses into smaller chunks to avoid maximum
IN clause lengths enforced by some database platforms.
- Author:
- Jeff Fischer
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic void
executeTargetedCacheInvalidation
(jakarta.persistence.EntityManager em, Class<?> entityType, List<Long> ids) static int
executeUpdateQuery
(jakarta.persistence.EntityManager em, String template, Object[] params, org.hibernate.type.Type[] types, List<Long> ids) Deprecated.Highly recommended not to use this method.static int
executeUpdateQuery
(jakarta.persistence.EntityManager em, String template, String tableSpace, Object[] params, org.hibernate.type.Type[] types, List<Long> ids) Perform an update query using a String template and params.
-
Constructor Details
-
UpdateExecutor
public UpdateExecutor()
-
-
Method Details
-
executeUpdateQuery
@Deprecated public static int executeUpdateQuery(jakarta.persistence.EntityManager em, String template, Object[] params, org.hibernate.type.Type[] types, List<Long> ids) Deprecated.Highly recommended not to use this method. This method results in global L2 cache region clearing. UseexecuteUpdateQuery(EntityManager, String, String, Object[], Type[], List)
instead.Perform an update query using a String template and params. Note, this is only intended for special usage with update queries that have an IN clause at the end. This implementation uses Hibernate Session directly to avoid a problem with assigning NULL values. The query should be written in native SQL. An example looks like: 'UPDATE BLC_SNDBX_WRKFLW_ITEM SET SCHEDULED_DATE = ? WHERE WRKFLW_SNDBX_ITEM_ID IN (%s)'- Parameters:
em
- The entity manager to use for the persistence operationtemplate
- the overall update sql template. The IN clause parameter should be written using 'IN (%s)'.params
- any other params that are present in the sql template, other than the IN clause. Should be written using '?'. Should be in order. Can be null.types
- theType
instances that identify the types for the params. Should be in order and match the length of params. Can be null.ids
- the ids to include in the IN clause.- Returns:
- the total number of records updated in the database
-
executeUpdateQuery
public static int executeUpdateQuery(jakarta.persistence.EntityManager em, String template, String tableSpace, Object[] params, org.hibernate.type.Type[] types, List<Long> ids) Perform an update query using a String template and params. Note, this is only intended for special usage with update queries that have an IN clause at the end. This implementation uses Hibernate Session directly to avoid a problem with assigning NULL values. The query should be written in native SQL. An example looks like: 'UPDATE BLC_SNDBX_WRKFLW_ITEM SET SCHEDULED_DATE = ? WHERE WRKFLW_SNDBX_ITEM_ID IN (%s)'- Parameters:
em
- The entity manager to use for the persistence operationtemplate
- the overall update sql template. The IN clause parameter should be written using 'IN (%s)'.tableSpace
- optionally provide the table being impacted by this query. This value allows Hibernate to limit the scope of cache region invalidation. Otherwise, if left null, Hibernate will invalidate every cache region, which is generally not desirable. An empty String can be used to signify that no region should be invalidated.params
- any other params that are present in the sql template, other than the IN clause. Should be written using '?'. Should be in order. Can be null.types
- theType
instances that identify the types for the params. Should be in order and match the length of params. Can be null.ids
- the ids to include in the IN clause.- Returns:
- the total number of records updated in the database
-
executeTargetedCacheInvalidation
public static void executeTargetedCacheInvalidation(jakarta.persistence.EntityManager em, Class<?> entityType, List<Long> ids) - Parameters:
em
-entityType
-ids
-
-