Database Documentation

1. Database

This section provides detailed information about the database architecture, configuration, and best practices for the Northbound API.

1.1. Database Overview

The application uses a multi-database architecture to interact with different data sources. The ACS backend can be served by either MySQL or Oracle depending on deployment requirements.

  1. ACS Database: Stores devices data including configurations, provisioning templates, and service definitions.

1.2. Database Configuration

1.2.1. Data Source Configuration

The application configures multiple data sources through Spring Boot properties. Each data source is configured with its own connection pool using HikariCP.

ACS Database Configuration (application-mysql.yml)
spring:
  datasource:
    acs:
      jdbc-url: ${MYSQL_JDBC_URL:jdbc:mysql://${MYSQL_HOST:${DB_HOST:localhost}}:${MYSQL_PORT:3306}/${MYSQL_SCHEMA:ftacs}?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC}
      username: ${MYSQL_USER:${DB_USERNAME:ftacs}}
      password: ${MYSQL_PASSWORD:ftacs}
      driver-class-name: ${MYSQL_DRIVER_CLASS_NAME:com.mysql.cj.jdbc.Driver}
      maximum-pool-size: ${DB_MAX_POOL_SIZE:10}
      minimum-idle: ${DB_MIN_IDLE:5}
      connection-timeout: ${DB_CONNECTION_TIMEOUT_MS:30000}

Configure the host, schema, and credentials through MYSQL_HOST, MYSQL_SCHEMA, MYSQL_USER, and MYSQL_PASSWORD, or override the entire string with MYSQL_JDBC_URL when you need extra connection parameters. The Oracle distribution mirrors these properties under application-oracle.yml, exposing ORACLE_HOST, ORACLE_SERVICE, ORACLE_USER, and ORACLE_JDBC_URL alongside the oracle.jdbc.OracleDriver.

1.2.2. JPA Configuration

Each database has its own EntityManagerFactory and TransactionManager configuration.

ACS Configuration

package com.friendly.northboundapi.config.db;

import com.friendly.apicommon.db.DatabaseType;
import com.friendly.apicommon.db.DbConfig;
import com.zaxxer.hikari.HikariDataSource;
import jakarta.persistence.EntityManagerFactory;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import java.util.HashMap;

@DependsOn("dbConfig")
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
@Configuration
@EnableJpaRepositories(
        basePackages = {"com.friendly"},
        entityManagerFactoryRef = "acsEntityManager",
        transactionManagerRef = "acsTransactionManager",
        includeFilters = @ComponentScan.Filter(
                type = FilterType.CUSTOM,
                classes = AcsSchemaFilter.class)
)
@Slf4j
@RequiredArgsConstructor
public class JpaAcsConfig {

    @NonNull
    private final Environment env;


    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.acs")
    public HikariDataSource acsDataSource() {
        HikariDataSource ds = new HikariDataSource();
        if (DbConfig.getDbType().equals(DatabaseType.Oracle)) {
            ds.setConnectionInitSql("ALTER SESSION SET TIME_ZONE='UTC'");
        }
        return ds;
    }

    @Bean
    public FactoryBean<EntityManagerFactory> acsEntityManager() {
        final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(acsDataSource());
        em.setPackagesToScan("com.friendly");

        final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        HashMap<String, Object> properties = new HashMap<>();

        properties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto"));
        properties.put("hibernate.dialect", DbConfig.getDbType().equals(DatabaseType.Oracle)
                ? env.getProperty("oracle.dialect") : env.getProperty("mysql.dialect"));
        properties.put("hibernate.enable_lazy_load_no_trans",
                env.getProperty("spring.jpa.properties.hibernate.enable_lazy_load_no_trans", "true"));
        properties.put("jpa.open-in-view", env.getProperty("spring.jpa.open-in-view", "true"));
        if (DbConfig.getDbType().equals(DatabaseType.Oracle)) {
            properties.put("hibernate.jdbc.time_zone", "UTC");
        }
        em.setJpaPropertyMap(properties);
        log.info("ACS DB properties: {}", properties);
        return em;
    }

    @Bean
    public PlatformTransactionManager acsTransactionManager(
            @Qualifier("acsEntityManager") EntityManagerFactory entityManager) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManager);
        return transactionManager;
    }
}

1.3. Database Schema

1.3.1. ACS Schema

The ACS schema contains tables used by the Northbound API for device management, provisioning, and operations. The schema must already exist before deploying the Northbound API — the application does not create or migrate tables.

Device Core
Table Purpose

cpe

Device records (serial number, manufacturer, model, OUI, connection status)

cpe_serial

Device serial number mappings

cust_device1

Custom device fields (user-defined attributes)

isp

Domains (ISP/location hierarchy)

product_class

Device model definitions

product_class_group

Device model groupings

manufacturer

Manufacturer records

Device Parameters & Methods
Table Purpose

cpe_parameter

Device parameter values

cpe_parameter_name

Parameter name definitions

cpe_method

Device method definitions

cpe_method_name

Method name definitions

Tasks & Transactions
Table Purpose

cpe_pending_task

Tasks waiting to be executed on devices

cpe_completed_task

Successfully completed tasks

cpe_failed_task

Tasks that failed execution

cpe_rejected_task

Tasks rejected by the device

transaction

Transaction tracking for async operations

Provisioning
Table Purpose

cpe_provision

Device provisioning definitions

cpe_provision_object

Provisioned object tree structures

cpe_provision_object_parameter

Parameters within provisioned objects

cpe_file

Files associated with device provisioning

Device Operations
Table Purpose

custom_rpc

Custom RPC method definitions

custom_rpc_history

Custom RPC execution history

cpe_diagnostic

Device diagnostic sessions

cpe_log

Device activity history

cpe_black_list

Device blacklist entries

cpe_activity_details

Detailed device activity records

files_ftp

FTP file management records

Authentication & Users
Table Purpose

cpe_login

ACS user credentials

spusers

Service provider user accounts (ftacs schema)

acs_info

ACS server metadata and version info (ftacs schema)

ftacs_parameter

ACS license parameters (ftacs schema)

API Logging
Table Purpose

process_log

API operation audit log (when api.settings.log.db=true)

process_stat

API call statistics (when api.settings.statistics=true)

1.4. Best Practices

1.4.1. Database Access

  1. Repository Pattern: Use Spring Data JPA repositories for database access

  2. Transaction Management: Use @Transactional annotation with appropriate transaction manager

  3. Entity Relationships: Define relationships with appropriate fetch strategies

  4. Pagination: Use paging and sorting repositories for large data sets

1.4.2. Performance Considerations

  1. Connection Pooling: Configure appropriate pool sizes based on load

  2. Query Optimization: Use indexed fields for filtering and sorting

  3. Batch Operations: Use batch inserts and updates for bulk operations

  4. Caching: Utilize caching for frequently accessed, rarely changing data

1.4.3. Database Security

  1. Parameter Binding: Always use parameterized queries to prevent SQL injection

  2. Minimal Privileges: Use database users with minimal required privileges

  3. Sensitive Data: Encrypt sensitive data at rest

  4. Audit Logging: Implement audit logging for critical data changes