test_class.declarator: sqlEntitiesPersister
test_class.modifier: @Autowired
    @Qualifier("sqlEntitiesPersister")
    private
test_class.original_string: @Autowired
    @Qualifier("sqlEntitiesPersister")
    private EntityPersister sqlEntitiesPersister;
test_class.type: EntityPersister
test_class.var_name: sqlEntitiesPersister
test_class.declarator: session
test_class.modifier: @Autowired private
test_class.original_string: @Autowired private Session session;
test_class.type: Session
test_class.var_name: session
test_class.declarator: sessionFactory
test_class.modifier: @Autowired private
test_class.original_string: @Autowired private SessionFactory sessionFactory;
test_class.type: SessionFactory
test_class.var_name: sessionFactory
test_class.declarator: config
test_class.modifier: @Autowired private
test_class.original_string: @Autowired private SqlReportEntitiesPersister.Config config;
test_class.type: SqlReportEntitiesPersister.Config
test_class.var_name: config
test_class.declarator: criteria
test_class.modifier: @Mock private
test_class.original_string: @Mock private Criteria criteria;
test_class.type: Criteria
test_class.var_name: criteria
test_class.declarator: sequence
test_class.modifier: private
test_class.original_string: private InOrder sequence;
test_class.type: InOrder
test_class.var_name: sequence
test_class.file: aw-reporting-model/src/test/java/com/google/api/ads/adwords/awreporting/model/persistence/sql/SqlReportEntitiesPersisterTest.java
test_class.identifier: SqlReportEntitiesPersisterTest
test_case.body: @Test
    public void persistReportEntities_retriesAfterDeadlockThenFails() {
      AccountPerformanceReport report = generateReport(1);
  
      Mockito.doThrow(new LockAcquisitionException("", null)).when(session).saveOrUpdate(any());
  
      try {
        sqlEntitiesPersister.persistReportEntities(Arrays.asList(report));
        fail();
      } catch (LockAcquisitionException ex) {
        // expected
      }
  
      sequence.verify(session, Mockito.times(20)).saveOrUpdate(report);
    }
test_case.class_method_signature: SqlReportEntitiesPersisterTest.persistReportEntities_retriesAfterDeadlockThenFails()
test_case.full_signature: @Test public void persistReportEntities_retriesAfterDeadlockThenFails()
test_case.identifier: persistReportEntities_retriesAfterDeadlockThenFails
test_case.invocations: generateReport saveOrUpdate when doThrow any persistReportEntities asList fail saveOrUpdate verify times
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void persistReportEntities_retriesAfterDeadlockThenFails()
focal_class.declarator: logger = LoggerFactory.getLogger(SqlReportEntitiesPersister.class)
focal_class.modifier: private static final
focal_class.original_string: private static final Logger logger = LoggerFactory.getLogger(SqlReportEntitiesPersister.class);
focal_class.type: Logger
focal_class.var_name: logger
focal_class.declarator: sessionFactory
focal_class.modifier: private final
focal_class.original_string: private final SessionFactory sessionFactory;
focal_class.type: SessionFactory
focal_class.var_name: sessionFactory
focal_class.declarator: config
focal_class.modifier: private final
focal_class.original_string: private final Config config;
focal_class.type: Config
focal_class.var_name: config
focal_class.file: aw-reporting-model/src/main/java/com/google/api/ads/adwords/awreporting/model/persistence/sql/SqlReportEntitiesPersister.java
focal_class.identifier: SqlReportEntitiesPersister
focal_class.interfaces: implements EntityPersister
focal_class.class_method_signature: SqlReportEntitiesPersister.SqlReportEntitiesPersister(SessionFactory sessionFactory, Config config)
focal_class.full_signature: @Autowired public  SqlReportEntitiesPersister(SessionFactory sessionFactory, Config config)
focal_class.identifier: SqlReportEntitiesPersister
focal_class.modifiers: @Autowired public
focal_class.parameters: (SessionFactory sessionFactory, Config config)
focal_class.signature:  SqlReportEntitiesPersister(SessionFactory sessionFactory, Config config)
focal_class.class_method_signature: SqlReportEntitiesPersister.persistReportEntities(List<? extends Report> reportEntities)
focal_class.full_signature: @Override @Transactional @Retryable( value = {LockAcquisitionException.class}, maxAttemptsExpression = "#{ @systemProperties['retryBackoff'] ?: 20}", backoff = @Backoff( delayExpression = "#{ @systemProperties['retryDelay'] ?: 100}", maxDelayExpression = "#{ @systemProperties['retryMaxDelay'] ?: 50000 }", multiplierExpression = "#{ @systemProperties['retryMultiplier'] ?: 1.5}")) public void persistReportEntities(List<? extends Report> reportEntities)
focal_class.identifier: persistReportEntities
focal_class.modifiers: @Override @Transactional @Retryable( value = {LockAcquisitionException.class}, maxAttemptsExpression = "#{ @systemProperties['retryBackoff'] ?: 20}", backoff = @Backoff( delayExpression = "#{ @systemProperties['retryDelay'] ?: 100}", maxDelayExpression = "#{ @systemProperties['retryMaxDelay'] ?: 50000 }", multiplierExpression = "#{ @systemProperties['retryMultiplier'] ?: 1.5}")) public
focal_class.parameters: (List<? extends Report> reportEntities)
focal_class.return: void
focal_class.signature: void persistReportEntities(List<? extends Report> reportEntities)
focal_class.class_method_signature: SqlReportEntitiesPersister.save(T t)
focal_class.full_signature: @Override @Transactional public T save(T t)
focal_class.identifier: save
focal_class.modifiers: @Override @Transactional public
focal_class.parameters: (T t)
focal_class.return: T
focal_class.signature: T save(T t)
focal_class.class_method_signature: SqlReportEntitiesPersister.createCriteria(Class<T> classT)
focal_class.full_signature: private Criteria createCriteria(Class<T> classT)
focal_class.identifier: createCriteria
focal_class.modifiers: private
focal_class.parameters: (Class<T> classT)
focal_class.return: Criteria
focal_class.signature: Criteria createCriteria(Class<T> classT)
focal_class.class_method_signature: SqlReportEntitiesPersister.get(Class<T> classT, String key, V value)
focal_class.full_signature: @SuppressWarnings("unchecked") @Override @Transactional(readOnly = true) public List<T> get(Class<T> classT, String key, V value)
focal_class.identifier: get
focal_class.modifiers: @SuppressWarnings("unchecked") @Override @Transactional(readOnly = true) public
focal_class.parameters: (Class<T> classT, String key, V value)
focal_class.return: List<T>
focal_class.signature: List<T> get(Class<T> classT, String key, V value)
focal_method.body: @Override
    @Transactional
    @Retryable(
        value = {LockAcquisitionException.class},
        maxAttemptsExpression = "#{ @systemProperties['retryBackoff'] ?: 20}",
        backoff =
            @Backoff(
                delayExpression = "#{ @systemProperties['retryDelay'] ?: 100}",
                maxDelayExpression = "#{ @systemProperties['retryMaxDelay'] ?: 50000 }",
                multiplierExpression = "#{ @systemProperties['retryMultiplier'] ?: 1.5}"))
    public void persistReportEntities(List<? extends Report> reportEntities) {
      int batchFlush = 0;
      Session session = sessionFactory.getCurrentSession();
      FlushMode previousFlushMode = session.getHibernateFlushMode();
      session.setHibernateFlushMode(FlushMode.MANUAL);
  
      try {
        for (Report report : reportEntities) {
          report.setRowId();
  
          session.saveOrUpdate(report);
          batchFlush++;
  
          if (batchFlush == config.getBatchSize()) {
            session.flush();
            session.clear();
            batchFlush = 0;
          }
        }
  
        if (batchFlush > 0) {
          session.flush();
          session.clear();
        }
      } catch (NonUniqueObjectException ex) {
        // Github issue 268 & 280
        //   https://github.com/googleads/aw-reporting/issues/268
        //   https://github.com/googleads/aw-reporting/issues/280
        //
        // Currently we allow specifying report definitions which do not include all primary key
        // fields. This leads to cryptic hibernate errors without providing a reasonable
        // resolution strategy.
        //
        // This fix explains where to find the list of primary key fields, but does not address
        // the underlying issue of allowing non-unique rows to be downloaded in the first place.
        //
        // Ideally we would guarantee uniqueness of rows without the user having to specify the
        // PK fields.
        // However, this would be a substantial migration for the AWReporting user base.
        // Instead, we just log a (hopefully) useful error message.
        // Also note that the error message assumes that reportEntities was not empty, because
        // otherwise the exception would not have been thrown.
        logger.error(
            "Duplicate row detected. This is most likely because your report definition does not "
                + "include the primary key fields defined in {}.setRowId(). "
                + "Please add the missing fields and try again.",
            reportEntities.get(0).getClass().getName());
        throw ex;
      } finally {
        session.setHibernateFlushMode(previousFlushMode);
      }
    }
focal_method.class_method_signature: SqlReportEntitiesPersister.persistReportEntities(List<? extends Report> reportEntities)
focal_method.full_signature: @Override @Transactional @Retryable( value = {LockAcquisitionException.class}, maxAttemptsExpression = "#{ @systemProperties['retryBackoff'] ?: 20}", backoff = @Backoff( delayExpression = "#{ @systemProperties['retryDelay'] ?: 100}", maxDelayExpression = "#{ @systemProperties['retryMaxDelay'] ?: 50000 }", multiplierExpression = "#{ @systemProperties['retryMultiplier'] ?: 1.5}")) public void persistReportEntities(List<? extends Report> reportEntities)
focal_method.identifier: persistReportEntities
focal_method.invocations: getCurrentSession getHibernateFlushMode setHibernateFlushMode setRowId saveOrUpdate getBatchSize flush clear flush clear error getName getClass get setHibernateFlushMode
focal_method.modifiers: @Override @Transactional @Retryable( value = {LockAcquisitionException.class}, maxAttemptsExpression = "#{ @systemProperties['retryBackoff'] ?: 20}", backoff = @Backoff( delayExpression = "#{ @systemProperties['retryDelay'] ?: 100}", maxDelayExpression = "#{ @systemProperties['retryMaxDelay'] ?: 50000 }", multiplierExpression = "#{ @systemProperties['retryMultiplier'] ?: 1.5}")) public
focal_method.parameters: (List<? extends Report> reportEntities)
focal_method.return: void
focal_method.signature: void persistReportEntities(List<? extends Report> reportEntities)