SAP / olingo-jpa-processor-v4

The JPA Processor fills the gap between Olingo V4 and the database, by providing a mapping between JPA metadata and OData metadata, generating queries and supporting the entity manipulations.
Apache License 2.0
123 stars 78 forks source link

Concept DatabaseProcessor is not working or not finished yet? #169

Closed alvachien closed 1 year ago

alvachien commented 2 years ago

Class JPAODataServiceContext has a method: setDatabaseProcessor

    /**
     * A database processor allows database specific implementations for search and odata function with function import
     * that are implemented as database functions.<br>
     * In case no database processor is provided and non could be determined via an data source
     * {@link JPADefaultDatabaseProcessor} is used.
     * @param databaseProcessor
     * @return
     */
    public Builder setDatabaseProcessor(final JPAODataDatabaseProcessor databaseProcessor) {
      this.databaseProcessor = databaseProcessor;
      return this;
    }

It seems that we can set it configuration:

  @Bean
  public JPAODataSessionContextAccess odataSessionContext(@Autowired final EntityManagerFactory emf) throws ODataException {

    return JPAODataServiceContext.with()
        .setPUnit(punit)
        .setEntityManagerFactory(emf)
        .setTypePackage(rootPackages)
        .setRequestMappingPath(requestMappingPath)
        .setDatabaseProcessor(processor) // <== Change the data base processor
        .build();
  }

However my local database processor never got caught, even all methods have been implemented. Have to jump into the codes of library, the database processor are created by the factory as below, which have no way for database processor at all.

public class JPAODataDatabaseProcessorFactory {
  private static final Log LOGGER = LogFactory.getLog(JPAODataDatabaseProcessorFactory.class);
  private static final String PRODUCT_NAME_H2 = "H2";
  private static final String PRODUCT_NAME_HSQLDB = "HSQL Database Engine";
  private static final String PRODUCT_NAME_POSTSQL = "PostgreSQL";

  public JPAODataDatabaseProcessor create(final DataSource ds) throws SQLException {
    if (ds != null) {
      try (Connection connection = ds.getConnection()) {
        final DatabaseMetaData dbMetadata = connection.getMetaData();
        if (dbMetadata.getDatabaseProductName().equals(PRODUCT_NAME_POSTSQL)) {
          LOGGER.trace("Create database-processor for PostgreSQL");
          return new JPA_POSTSQL_DatabaseProcessor();
        } else if (dbMetadata.getDatabaseProductName().equals(PRODUCT_NAME_HSQLDB)) {
          LOGGER.trace("Create database-processor for HSQLDB");
          return new JPA_HSQLDB_DatabaseProcessor();
        } else if (dbMetadata.getDatabaseProductName().equals(PRODUCT_NAME_H2)) {
          LOGGER.trace("Create database-processor for H2");
          return new JPA_HSQLDB_DatabaseProcessor();
        } else {
          LOGGER.trace("Create default database-processor");
          return new JPADefaultDatabaseProcessor();
        }
      }
    } else {
      LOGGER.trace("Create default database-processor");
      return new JPADefaultDatabaseProcessor();
    }
  }
}

So, the concept 'Database Processor' is not working or it is not yet finished?

Thank you. Alva

wog48 commented 2 years ago

Actually I cannot reproduce the problem. In the builder the JPAODataDatabaseProcessorFactory is only used in case no database processor is provided:

   public JPAODataSessionContextAccess build() throws ODataException {
      try {
        if (nameBuilder == null) {
          LOGGER.trace("No name-builder provided, use JPADefaultEdmNameBuilder");
          nameBuilder = new JPADefaultEdmNameBuilder(namespace);
        }
        if (packageName == null)
          packageName = new String[0];
        if (!emf.isPresent() && ds != null && namespace != null)
          emf = Optional.ofNullable(JPAEntityManagerFactory.getEntityManagerFactory(namespace, ds));
        createEmfWrapper();
        if (emf.isPresent() && jpaEdm == null)
          jpaEdm = new JPAEdmProvider(emf.get().getMetamodel(), postProcessor, packageName, nameBuilder);
        if (databaseProcessor == null) {
          LOGGER.trace("No database-processor provided, use JPAODataDatabaseProcessorFactory to create one");
          databaseProcessor = new JPAODataDatabaseProcessorFactory().create(ds);
        }
        if (batchProcessorFactory == null) {
          LOGGER.trace("No batch-processor-factory provided, use default factory to create one");
          batchProcessorFactory = new JPADefaultBatchProcessorFactory();
        }
      } catch (SQLException | PersistenceException e) {
        throw new ODataJPAFilterException(e, HttpStatusCode.INTERNAL_SERVER_ERROR);
      }
      return new JPAODataServiceContext(this);
    }

Is there one method that is not called?

alvachien commented 2 years ago

Thanks for the reply.

But still, my own processor cannot be called with CRUD operations.

Or, could you mind share me some lights which method (via interface JPAODataDatabaseOperations) can be called?

Thank you.

wog48 commented 2 years ago

Many be there is a miss understanding. For the CUD operations an implementation of JPACUDRequestHandler is needed. An instance is provided via the JPAODataRequestContext. The goal of the JPAODataDatabaseProcessor is to support function that are implemented on the data base.

wog48 commented 1 year ago

I close the issue. Feel free to reopen it in case your question is not answered.