killbill-aplcache

util: switch to getByIds queries in EntitySqlDaoWrapperInvocationHandler Signed-off-by:

2/7/2019 6:29:57 AM

Details

diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.java
index b1533de..61cc91e 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.java
@@ -19,7 +19,6 @@
 package org.killbill.billing.invoice.dao;
 
 import java.math.BigDecimal;
-import java.util.Collection;
 import java.util.List;
 
 import org.killbill.billing.callcontext.InternalCallContext;
@@ -33,7 +32,6 @@ import org.killbill.commons.jdbi.template.KillBillSqlDaoStringTemplate;
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.unstable.BindIn;
 
 @KillBillSqlDaoStringTemplate
 public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItemModelDao, InvoiceItem> {
@@ -64,8 +62,4 @@ public interface InvoiceItemSqlDao extends EntitySqlDao<InvoiceItemModelDao, Inv
 
     @SqlQuery
     BigDecimal getAccountCBA(@SmartBindBean final InternalTenantContext context);
-
-    @SqlQuery
-    List<InvoiceItemModelDao> getByIds(@BindIn("ids") final Collection<String> invoiceItemIds,
-                                       @SmartBindBean final InternalTenantContext context);
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java
index d0b8e1b..3c85d8e 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
  *
  * The Billing Project licenses this file to you under the Apache License, version 2.0
  * (the "License"); you may not use this file except in compliance with the
@@ -18,7 +18,6 @@
 
 package org.killbill.billing.invoice.dao;
 
-import java.util.Collection;
 import java.util.List;
 import java.util.UUID;
 
@@ -33,7 +32,6 @@ import org.killbill.commons.jdbi.template.KillBillSqlDaoStringTemplate;
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.unstable.BindIn;
 
 @KillBillSqlDaoStringTemplate
 public interface InvoiceSqlDao extends EntitySqlDao<InvoiceModelDao, Invoice> {
@@ -59,11 +57,5 @@ public interface InvoiceSqlDao extends EntitySqlDao<InvoiceModelDao, Invoice> {
     @SqlQuery
     InvoiceModelDao getParentDraftInvoice(@Bind("accountId") final String parentAccountId,
                                           @SmartBindBean final InternalTenantContext context);
-
-    @SqlQuery
-    List<InvoiceModelDao> getByIds(@BindIn("ids") final Collection<String> invoiceIds,
-                                   @SmartBindBean final InternalTenantContext context);
-
-
 }
 
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.sql.stg b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
index 7ac7570..1a25b85 100644
--- a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceItemSqlDao.sql.stg
@@ -50,15 +50,6 @@ tableValues() ::= <<
 , :createdDate
 >>
 
-getByIds(ids) ::= <<
-select
-  <allTableFields("t.")>
-from <tableName()> t
-where <idField("t.")> in (<ids>)
-<AND_CHECK_TENANT("t.")>
-;
->>
-
 getInvoiceItemsByInvoice() ::= <<
   SELECT <allTableFields("")>
   FROM <tableName()>
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg
index ab5923a..304ef0e 100644
--- a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg
@@ -82,12 +82,3 @@ getParentDraftInvoice() ::= <<
    <defaultOrderBy("")>
 >>
 
-
-getByIds(ids) ::= <<
-select
-  <allTableFields("t.")>
-from <tableName()> t
-where <idField("t.")> in (<ids>)
-<AND_CHECK_TENANT("t.")>
-;
->>
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDao.java b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDao.java
index 974e23b..284bb60 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDao.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDao.java
@@ -18,6 +18,7 @@
 
 package org.killbill.billing.util.entity.dao;
 
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
@@ -39,6 +40,7 @@ import org.skife.jdbi.v2.sqlobject.customizers.BatchChunkSize;
 import org.skife.jdbi.v2.sqlobject.customizers.Define;
 import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
 import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.unstable.BindIn;
 import org.skife.jdbi.v2.util.LongMapper;
 
 @KillBillSqlDaoStringTemplate
@@ -66,6 +68,10 @@ public interface EntitySqlDao<M extends EntityModelDao<E>, E extends Entity> ext
                            @SmartBindBean final InternalTenantContext context);
 
     @SqlQuery
+    List<M> getByIds(@BindIn("ids") final Collection<String> ids,
+                     @SmartBindBean final InternalTenantContext context);
+
+    @SqlQuery
     public List<M> getByAccountRecordId(@SmartBindBean final InternalTenantContext context);
 
     @SqlQuery
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
index 63a99ff..a95b56d 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDaoWrapperInvocationHandler.java
@@ -219,13 +219,15 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
         final boolean isBatchQuery = method.getAnnotation(SqlBatch.class) != null;
 
         // Get the current state before deletion for the history tables
-        final Map<Long, M> deletedEntities = new HashMap<Long, M>();
+        final Map<Long, M> deletedAndUpdatedEntities = new HashMap<Long, M>();
         if (changeType == ChangeType.DELETE) {
-            for (final String entityId : entityIds) {
-                // TODO Switch to getByIds
-                final M entityToBeDeleted = sqlDao.getById(entityId, contextMaybeWithoutAccountRecordId);
-                deletedEntities.put(entityToBeDeleted.getRecordId(), entityToBeDeleted);
+            // TODO FIXME: this shouldn't happen (auditing for InvoiceTrackingSqlDao is broken)
+            if (!entityIds.isEmpty()) {
+                final List<M> entitiesToBeDeleted = sqlDao.getByIds(entityIds, contextMaybeWithoutAccountRecordId);
                 printSQLWarnings();
+                for (final M entityToBeDeleted : entitiesToBeDeleted) {
+                    deletedAndUpdatedEntities.put(entityToBeDeleted.getRecordId(), entityToBeDeleted);
+                }
             }
         }
 
@@ -245,13 +247,13 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
         // Retrieve record_id(s) for audit and history tables
         final List<Long> entityRecordIds = new LinkedList<Long>();
         if (changeType == ChangeType.DELETE) {
-            for (final Long entityRecordId : deletedEntities.keySet()) {
-                final M entity = deletedEntities.get(entityRecordId);
+            for (final Long entityRecordId : deletedAndUpdatedEntities.keySet()) {
+                final M entity = deletedAndUpdatedEntities.get(entityRecordId);
                 entityRecordIds.add(entityRecordId);
                 if (tableName == null) {
                     tableName = entity.getTableName();
                 } else {
-                    Preconditions.checkState(tableName == entity.getTableName(), "Entities with different TableName: %s", deletedEntities);
+                    Preconditions.checkState(tableName == entity.getTableName(), "Entities with different TableName: %s", deletedAndUpdatedEntities);
                 }
             }
         } else if (changeType == ChangeType.INSERT && !isBatchQuery) {
@@ -268,12 +270,11 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
                 context = internalCallContextFactory.createInternalCallContext(accountModelDao, accountRecordId, contextMaybeWithoutAccountRecordId);
             }
         } else {
-            for (final String entityId : entityIds) {
-                // For batch inserts and updates, easiest is to go back to the database
-                // TODO Do we go to the cache here?
-                // TODO Switch to getByIds
-                final M entity = sqlDao.getById(entityId, contextMaybeWithoutAccountRecordId);
-                printSQLWarnings();
+            // For batch inserts and updates, easiest is to go back to the database
+            final List<M> retrievedEntities = sqlDao.getByIds(entityIds, contextMaybeWithoutAccountRecordId);
+            printSQLWarnings();
+            for (final M entity : retrievedEntities) {
+                deletedAndUpdatedEntities.put(entity.getRecordId(), entity);
                 entityRecordIds.add(entity.getRecordId());
                 if (tableName == null) {
                     tableName = entity.getTableName();
@@ -294,7 +295,7 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
                                      "accountRecordId should be set for tableName=%s and changeType=%s", tableName, changeType);
         }
 
-        final List<M> reHydratedEntitiesOrNull = updateHistoryAndAudit(entityRecordIds, deletedEntities, tableName, changeType, context);
+        final Collection<M> reHydratedEntities = updateHistoryAndAudit(entityRecordIds, deletedAndUpdatedEntities, tableName, changeType, context);
         if (method.getReturnType().equals(Void.TYPE)) {
             // Return early
             return null;
@@ -306,12 +307,14 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
             // (see EntityDaoBase#createAndRefresh for an example, but it works for updates as well).
             Preconditions.checkState(entityRecordIds.size() == 1, "Invalid number of entityRecordIds: %s", entityRecordIds);
 
-            if (reHydratedEntitiesOrNull != null) {
-                Preconditions.checkState(reHydratedEntitiesOrNull.size() == 1, "Invalid number of entities: %s", reHydratedEntitiesOrNull);
-                return Iterables.<M>getFirst(reHydratedEntitiesOrNull, null);
+            if (!reHydratedEntities.isEmpty()) {
+                Preconditions.checkState(reHydratedEntities.size() == 1, "Invalid number of entities: %s", reHydratedEntities);
+                return Iterables.<M>getFirst(reHydratedEntities, null);
             } else {
                 // Updated entity not retrieved yet, we have to go back to the database
-                return sqlDao.getByRecordId(entityRecordIds.get(0), context);
+                final M entity = sqlDao.getByRecordId(entityRecordIds.get(0), context);
+                printSQLWarnings();
+                return entity;
             }
         }
     }
@@ -367,25 +370,31 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
 
     // Update history and audit tables.
     // PERF: if the latest entities had to be fetched from the database, return them. Otherwise, return null.
-    private List<M> updateHistoryAndAudit(final Collection<Long> entityRecordIds,
-                                          final Map<Long, M> deletedEntities,
-                                          final TableName tableName,
-                                          final ChangeType changeType,
-                                          final InternalCallContext context) throws Throwable {
+    private Collection<M> updateHistoryAndAudit(final Collection<Long> entityRecordIds,
+                                                final Map<Long, M> deletedAndUpdatedEntities,
+                                                final TableName tableName,
+                                                final ChangeType changeType,
+                                                final InternalCallContext context) throws Throwable {
         final Object reHydratedEntitiesOrNull = prof.executeWithProfiling(ProfilingFeatureType.DAO_DETAILS, getProfilingId("history/audit", null), new WithProfilingCallback<Object, Throwable>() {
             @Override
-            public List<M> execute() {
+            public Collection<M> execute() {
                 if (tableName.getHistoryTableName() == null) {
                     insertAudits(entityRecordIds, tableName, changeType, context);
-                    return null;
+                    return deletedAndUpdatedEntities.values();
                 } else {
                     // We'll keep the ordering
                     final Collection<Long> auditTargetRecordIds = new ArrayList<>(entityRecordIds.size());
-                    final List<M> reHydratedEntities = new ArrayList<>(entityRecordIds.size());
+                    final Collection<M> reHydratedEntities = new ArrayList<>(entityRecordIds.size());
                     for (final Long entityRecordId : entityRecordIds) {
                         // Make sure to re-hydrate the objects first (especially needed for create calls)
                         // TODO Could we do this in bulk too?
-                        final M reHydratedEntityModelDao = MoreObjects.firstNonNull(deletedEntities.get(entityRecordId), sqlDao.getByRecordId(entityRecordId, context));
+                        final M reHydratedEntityModelDao;
+                        if (deletedAndUpdatedEntities.keySet().contains(entityRecordId)) {
+                            reHydratedEntityModelDao = deletedAndUpdatedEntities.get(entityRecordId);
+                        } else {
+                            reHydratedEntityModelDao = sqlDao.getByRecordId(entityRecordId, context);
+                            printSQLWarnings();
+                        }
                         final Long auditTargetRecordId = insertHistory(reHydratedEntityModelDao, changeType, context);
                         auditTargetRecordIds.add(auditTargetRecordId);
                         reHydratedEntities.add(reHydratedEntityModelDao);
@@ -398,7 +407,7 @@ public class EntitySqlDaoWrapperInvocationHandler<S extends EntitySqlDao<M, E>, 
             }
         });
         //noinspection unchecked
-        return (List<M>) reHydratedEntitiesOrNull;
+        return (Collection<M>) reHydratedEntitiesOrNull;
     }
 
     private List<String> retrieveEntityIdsFromArguments(final Method method, final Object[] args) {
diff --git a/util/src/main/java/org/killbill/billing/util/tag/dao/TagDefinitionSqlDao.java b/util/src/main/java/org/killbill/billing/util/tag/dao/TagDefinitionSqlDao.java
index 929fa42..4c5ab00 100644
--- a/util/src/main/java/org/killbill/billing/util/tag/dao/TagDefinitionSqlDao.java
+++ b/util/src/main/java/org/killbill/billing/util/tag/dao/TagDefinitionSqlDao.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 The Billing Project, LLC
  *
  * The Billing Project licenses this file to you under the Apache License, version 2.0
  * (the "License"); you may not use this file except in compliance with the
@@ -18,9 +18,6 @@
 
 package org.killbill.billing.util.tag.dao;
 
-import java.util.Collection;
-import java.util.List;
-
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.util.audit.ChangeType;
@@ -32,7 +29,6 @@ import org.killbill.commons.jdbi.template.KillBillSqlDaoStringTemplate;
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.unstable.BindIn;
 
 @KillBillSqlDaoStringTemplate
 public interface TagDefinitionSqlDao extends EntitySqlDao<TagDefinitionModelDao, TagDefinition> {
@@ -49,8 +45,4 @@ public interface TagDefinitionSqlDao extends EntitySqlDao<TagDefinitionModelDao,
     @SqlQuery
     public int tagDefinitionUsageCount(@Bind("id") final String definitionId,
                                        @SmartBindBean final InternalTenantContext context);
-
-    @SqlQuery
-    public List<TagDefinitionModelDao> getByIds(@BindIn("ids") final Collection<String> definitionIds,
-                                                @SmartBindBean final InternalTenantContext context);
 }
diff --git a/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg b/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg
index ab7f88f..67fa072 100644
--- a/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg
+++ b/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg
@@ -189,6 +189,17 @@ where <recordIdField("t.")> = :recordId
 ;
 >>
 
+getByIds(ids) ::= <<
+select
+  <allTableFields("t.")>
+from <tableName()> t
+where <idField("t.")> in (<ids>)
+<andCheckSoftDeletionWithComma("t.")>
+<AND_CHECK_TENANT("t.")>
+<defaultOrderBy("t.")>
+;
+>>
+
 /** Note: account_record_id can be NULL **/
 getByAccountRecordId(accountRecordId) ::= <<
 select
diff --git a/util/src/main/resources/org/killbill/billing/util/tag/dao/TagDefinitionSqlDao.sql.stg b/util/src/main/resources/org/killbill/billing/util/tag/dao/TagDefinitionSqlDao.sql.stg
index 1328fc6..e7110f7 100644
--- a/util/src/main/resources/org/killbill/billing/util/tag/dao/TagDefinitionSqlDao.sql.stg
+++ b/util/src/main/resources/org/killbill/billing/util/tag/dao/TagDefinitionSqlDao.sql.stg
@@ -59,15 +59,3 @@ and t.is_active
 <AND_CHECK_TENANT("t.")>
 ;
 >>
-
-getByIds(ids) ::= <<
-select
-  <allTableFields("t.")>
-from <tableName()> t
-where t.is_active
-and <idField("t.")> in (<ids>)
-<AND_CHECK_TENANT("t.")>
-<defaultOrderBy("t.")>
-;
->>
-