Persistence
Persisting data is one of the most common functions in backend services. There are many good persistence frameworks available on the market and the Pip.Services toolkit doesn’t intend to compete with them. Using the Component Model the toolkit integrates selected best of breed persistence technologies to enable consistent configuration, management and the use of the symmetric programming model across different databases and languages.
Out of the box, the Pip.Services toolkit offers support for a number of persistence technologies and popular relational and NoSQL databases (implementations for different languages may vary). They are:
- In-memory persistence
- File persistence
- SQL Server
- MySQL
- Postresql
- SQLite
- MongoDB
- Couchbase
- Cassandra
Connection Management
The XyzConnection component encapsulates database connections and configures them like on the example config file below:
# Database connection
descriptor: pip-services:connection:mongodb:default:3.0
connection:
host: ${{MONGO_HOST}}{$unless MONGO_HOST}localhost{$unless}
port: ${{MONGO_PORT}}{$unless MONGO_PORT}27017{$unless}
credentials:
host: ${{MONGO_USER}}{$unless MONGO_USER}mongo{$unless}
port: ${{MONGO_PASS}}{$unless MONGO_PASS}pwd123{$unless}
options:
max_pool_size: 10
keep_alive: true
Using the connection.discovery_key
parameter, the connection component can retrieve connection parameters from Discovery Services and, using the credentials.store_key
parameter, it can retrieve credential parameters from Credential Stores.
By default, persistence components will try to retrieve the first available connection from the references. By specifying the references.connection
parameter, a persistence component can be linked with a specific connection. If there are no connections available, each persistence component will try to create its own connection. See the sample config below:
# Persistence with default connection
descriptor: myservice:mypersistence:mongodb:persist1:1.0
# Persistence linked to specific connection
descriptor: myservice:mypersistence:mongodb:persist2:1.0
references:
connection: pip-services:connection:mongodb:conn1:3.0
Most XyzConnection components have the getConnection() method (Connection property) to get a reference to a shared database connection.
Generic Persistence
For persistence operations against a single table (collection) the toolkit offers XyzPersistence components. They act as abstract classes for specific implementations that enable the component lifecycle and share database connections. Persistence operations can be implemented using custom code or a number of out-of-the-box methods like GetListByFilter(), Create() or DeleteByFilter().
import { MongoDbPersistence } from 'pip-services3-mongodb-nodex';
class MyObject {
key: string;
name: string;
}
class MyMongoDbPersistence extends MongoDbPersistence<MyObject> {
public constructor() {
super("mycollection");
}
public async getByName(correlationId: string, name: string): Promise<MyObject> {
let criteria= { name: name };
let res = await super.getListByFilter(correlationId, criteria, null, null);
return res.length > 0 ? res[0] : null;
}
public async createDefault(correlationId: string, name: string): Promise<MyObject> {
name = name ?? "unknown";
let key = name.toLowerCase().replace(" #$%^&", "_");
let item: MyObject = { key: key, name: name };
let result = await new Promise<any>((resolve, reject) => {
this._collection.insertOne(item, (err, result) => {
if (err = null) resolve(result);
else reject(err);
});
});
this._logger.trace(correlationId, "Created item in %s with key = %s", this._collectionName, key);
let newItem = result != null ? result.ops[0] : null;
return newItem;
}
public async deleteByName(correlationId: string, name: string): Promise<void> {
let criteria= { name: name };
await super.deleteByFilter(correlationId, criteria);
}
}
using PipServices3.MongoDb.Persistence;
using MongoDB.Bson.Serialization.Attributes;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using MongoDB.Driver;
class MyObject
{
[BsonElement("key")]
[DataMember(Name = "key")]
public string Key { get; set; }
[BsonElement("name")]
[DataMember(Name = "name")]
public string Name { get; set; }
}
class MyMongoDbPersistence : MongoDbPersistence<MyObject>
{
public MyMongoDbPersistence():base("mycollection") { }
public async Task<MyObject> GetByNameAsync(string correlationId, string name)
{
var builder = Builders<MyObject>.Filter;
var filter = builder.Empty;
filter &= builder.Eq("name", name); ;
var res = await GetListByFilterAsync(correlationId, filter);
return res.Count > 0 ? res[0] : null;
}
public async Task<MyObject> CreateDefault(string correlationId, string name)
{
name ??= "unknown";
var key = name.ToLower().Replace(" #$%^&", "_");
var item = new MyObject { Key = key, Name = name };
await _collection.InsertOneAsync(item, null);
_logger.Trace(correlationId, "Created item in %s with key = %s", _collectionName, key);
return item;
}
public async Task DeleteByName(string correlationId, string name)
{
var builder = Builders<MyObject>.Filter;
var filter = builder.Empty;
filter &= builder.Eq("name", name); ;
await DeleteByFilterAsync(correlationId, filter);
}
}
import (
"context"
"strings"
persist "github.com/pip-services3-gox/pip-services3-mongodb-gox/persistence"
"go.mongodb.org/mongo-driver/bson"
)
type MyObject struct {
Key string `bson:"key" json:"key"`
Name string `bson:"name" json:"name"`
}
type MyMongoDbPersistence struct {
*persist.MongoDbPersistence[MyObject]
}
func NewMyMongoDbPersistence() *MyMongoDbPersistence {
c := &MyMongoDbPersistence{}
c.MongoDbPersistence = persist.InheritMongoDbPersistence[MyObject](c, "mycollection")
return c
}
func (c *MyMongoDbPersistence) GetByName(ctx context.Context, correlationId string,
name string) (result MyObject, err error) {
filterObj := bson.M{"name": name}
items, err := c.MongoDbPersistence.GetListByFilter(ctx, correlationId, filterObj, nil, nil)
if err != nil {
return result, err
}
if len(items) > 0 {
return items[0], nil
} else {
return result, nil
}
}
func (c *MyMongoDbPersistence) CreateDefault(ctx context.Context, correlationId string,
name string) (result MyObject, err error) {
if name == "" {
name = "unknown"
}
key := strings.ReplaceAll(strings.ToLower(name), " #$%^&", "_")
item := MyObject{Key: key, Name: name}
newItem, err := c.Overrides.ConvertFromPublic(item)
if err != nil {
return result, err
}
insRes, err := c.Collection.InsertOne(ctx, newItem)
if err != nil {
return result, err
}
result, err = c.Overrides.ConvertToPublic(newItem)
if err != nil {
return result, err
}
c.Logger.Trace(ctx, correlationId, "Created in %s with id = %s", c.Collection, insRes.InsertedID)
return result, nil
}
func (c *MyMongoDbPersistence) DeleteByName(ctx context.Context, correlationId string,
name string) error {
filterObj := bson.M{"name": name}
return c.DeleteByFilter(ctx, correlationId, filterObj)
}
import 'package:pip_services3_mongodb/pip_services3_mongodb.dart';
class MyObject {
String key;
String name;
MyObject.from(this.key, this.name);
Map<String, dynamic> toJson() {
return <String, dynamic>{'key': key, 'name': name};
}
void fromJson(Map<String, dynamic> json) {
key = json['key'];
name = json['name'];
}
MyObject clone() {
return MyObject.from(key, name);
}
}
class MyMongoDbPersistence extends MongoDbPersistence<MyObject> {
MyMongoDbPersistence() : super('mycollection');
Future<MyObject?> getByName(String correlationId, String name) async {
var criteria = {name: name};
var res = await super.getListByFilterEx(correlationId, criteria, null);
return res.isNotEmpty ? res[0] : null;
}
Future<MyObject?> createDefault(String correlationId, String name) async {
name = name ?? 'unknown';
var key = name.toLowerCase().replaceAll(' #\$%^&', '_');
var item = MyObject.from(key, name);
var jsonMap = convertFromPublic(item, createUid: false);
var result = await collection!.insertOne(jsonMap!);
logger.trace(correlationId, 'Created in %s with id = %s',
[collectionName, result.id]);
return convertToPublic(jsonMap);
}
Future<void> deleteByName(String correlationId, String name) async {
var criteria = {name: name};
await super.deleteByFilterEx(correlationId, criteria);
}
}
from pip_services3_mongodb.persistence import MongoDbPersistence
class MyObject:
def __init__(self, key: str = None, name: str = None):
self.name = key
self.content = name
class MyMongoDbPersistence(MongoDbPersistence):
def __init__(self):
super(MyMongoDbPersistence, self).__init__('mycollection')
def get_by_name(self, correlation_id: str, name: str) -> MyObject:
criteria = {'name': name}
res = self.get_list_by_filter(correlation_id, criteria, None, None)
return None if len(res) < 0 else res[0]
def create_default(self, correlation_id: str, name: str) -> MyObject:
name = name or 'unknown'
key = name.lower().replace(" #$%^&", "_")
item = MyObject(key, name)
result = self._collection.insert_one(item)
item = self._collection.find_one({'_id': result.inserted_id})
item = self._convert_to_public(item)
return item
def delete_by_name(self, correlation_id: str, name: str):
criteria = {'name': name}
self.delete_by_filter(correlation_id, criteria)
To implement custom persistence operations, protected properties should be used to get access to database connection, transaction and table (collection) object references encapsulated by the component (check the component documentation for details).
Identifiable Persistence
The most common persistence scenario is when data objects are identified by a unique Id field and stored in a single table (collection). This allows to implement persistence that can work against any relational or NoSQL persistence store available now or in the future (see concept Long-Living Code). To support this scenario the Pip.Services toolkit has the XyzIdentifiablePersistence
components that offer a full set of CRUD operations for objects that have the Id property and implement the IIdentifiable
interface.
import { IIdentifiable } from 'pip-services3-commons-nodex';
class MyIdentifiableObject implements IIdentifiable <string> {
public id: string;
public name: string;
public value: string;
}
using PipServices3.Commons.Data;
class MyIdentifiableObject: IIdentifiable<string>
{
[BsonElement("id")]
[DataMember(Name = "id")]
public string Id { get; set; }
[BsonElement("key")]
[DataMember(Name = "key")]
public string Key { get; set; }
[BsonElement("name")]
[DataMember(Name = "name")]
public string Name { get; set; }
}
type MyIdentifiableObject struct {
Id string `bson:"id" json:"id"`
Name string `bson:"name" json:"name"`
Value string `bson:"value" json:"value"`
}
func (c *MyIdentifiableObject) GetId() string {
return c.Id
}
import 'package:pip_services3_commons/pip_services3_commons.dart';
class MyIdentifiableObject implements IIdentifiable<String> {
@override
String? id;
String key;
String name;
MyIdentifiableObject.from(this.id, this.key, this.name);
Map<String, dynamic> toJson() {
return <String, dynamic>{'id': id, 'key': key, 'name': name};
}
void fromJson(Map<String, dynamic> json) {
key = json['key'];
name = json['name'];
}
MyIdentifiableObject clone() {
return MyIdentifiableObject.from(id, key, name);
}
}
from pip_services3_commons.data import IIdentifiable
class MyIdentifiableObject(IIdentifiable):
def __init__(self, id: str = None, name: str = None, value: str = None):
self.id = id
self.name = name
self.value = value
Unique ids can be natural or generated by a special key generator. However, to make it simpler and portable, the toolkit has the IdGenerator class that can generate globally unique Ids as string GUIDs. Those ids are quite long (32 characters) but they work well for collections of moderate size.
The example below requires only a few lines of code, but implements a persistence with a full set of CRUD operations:
import { IIdentifiable } from 'pip-services3-commons-nodex';
import { DataPage, FilterParams, PagingParams } from 'pip-services3-commons-nodex';
import { IdentifiablePostgresPersistence } from 'pip-services3-postgres-nodex';
class MyIdentifiableObject implements IIdentifiable <string> {
public id: string;
public name: string;
public value: string;
}
interface MyIdentifiablePersistence {
getPageByFilter(correlationId: string, filter: FilterParams, paging: PagingParams): Promise<DataPage<MyIdentifiableObject>>;
create(correlationId: string, item: MyIdentifiableObject): Promise<MyIdentifiableObject>;
getOneById(correlationId: string, id: string): Promise<MyIdentifiableObject>;
deleteById(correlationId: string, id: string): Promise<MyIdentifiableObject>;
}
class MyIdentifiablePostgreSqlPersistence extends IdentifiablePostgresPersistence<MyIdentifiableObject, string> implements MyIdentifiablePersistence {
public constructor() {
super("mycollection");
}
public composeFilter(filter: FilterParams): string {
filter = filter ?? new FilterParams();
let criteria = [];
let id = filter.getAsString("id");
if (id != null) {
criteria.push("id='" + id + "'");
}
let name = filter.getAsString("name");
if (name != null) {
criteria.push("name='" + name + "'");
}
return criteria.length > 0 ? criteria.join(" AND ") : null;
}
public async getPageByFilter(correlationId: string, filter: FilterParams, paging: PagingParams): Promise<DataPage<MyIdentifiableObject>> {
let criteria = this.composeFilter(filter);
return await super.getPageByFilter(correlationId, criteria, paging, null, null);
}
}
using MongoDB.Bson.Serialization.Attributes;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using PipServices3.Commons.Data;
using PipServices3.Postgres.Persistence;
using System.Collections.Generic;
class MyIdentifiableObject : IIdentifiable<string>
{
[BsonElement("id")]
[DataMember(Name = "id")]
public string Id { get; set; }
[BsonElement("key")]
[DataMember(Name = "key")]
public string Key { get; set; }
[BsonElement("name")]
[DataMember(Name = "name")]
public string Name { get; set; }
}
interface MyIdentifiablePersistence
{
Task<DataPage<MyIdentifiableObject>> GetPageByFilterAsync(string correlationId, FilterParams filter, PagingParams paging);
Task<MyIdentifiableObject> CreateAsync(string correlationId, MyIdentifiableObject item);
Task<MyIdentifiableObject> GetOneByIdAsync(string correlationId, string id);
Task<MyIdentifiableObject> DeleteByIdAsync(string correlationId, string id);
}
class MyMongoDbPersistence : IdentifiablePostgresPersistence<MyIdentifiableObject, string>, MyIdentifiablePersistence
{
public MyMongoDbPersistence() : base("mycollection") { }
private string composeFilter(FilterParams filter)
{
filter = filter ?? new FilterParams();
var criteria = new List<string>();
var id = filter.GetAsString("id");
if (id != null)
criteria.Add("id='" + id + "'");
var name = filter.GetAsString("name");
if (name != null)
criteria.Add("name='" + name + "'");
return criteria.Count > 0 ? string.Join(" AND ", criteria) : null;
}
public async Task<DataPage<MyIdentifiableObject>> GetPageByFilterAsync(string correlationId, FilterParams filter, PagingParams paging)
{
return await base.GetPageByFilterAsync(correlationId, composeFilter(filter), paging);
}
}
import (
"context"
"strings"
"github.com/pip-services3-gox/pip-services3-commons-gox/data"
"github.com/pip-services3-gox/pip-services3-postgres-gox/persistence"
)
type MyIdentifiableObject struct {
Id string `bson:"id" json:"id"`
Name string `bson:"name" json:"name"`
Value string `bson:"value" json:"value"`
}
func (c *MyIdentifiableObject) GetId() string {
return c.Id
}
type MyIdentifiablePersistence interface {
GetPageByFilter(correlationId string, filter data.FilterParams, paging data.PagingParams) (data.DataPage[MyIdentifiableObject], error)
Create(correlationId string, item MyIdentifiableObject) (MyIdentifiableObject, error)
GetOneById(correlationId string, id string) (MyIdentifiableObject, error)
DeleteById(correlationId string, id string) (MyIdentifiableObject, error)
}
type MyIdentifiablePostgreSqlPersistence struct {
*persistence.IdentifiablePostgresPersistence[MyIdentifiableObject, string]
}
func NewMyIdentifiablePostgreSqlPersistence() *MyIdentifiablePostgreSqlPersistence {
c := &MyIdentifiablePostgreSqlPersistence{}
c.IdentifiablePostgresPersistence = persistence.InheritIdentifiablePostgresPersistence[MyIdentifiableObject, string](c, "mycollection")
return c
}
func (c *MyIdentifiablePostgreSqlPersistence) composeFilter(filter data.FilterParams) string {
criteria := make([]string, 0)
if id, ok := filter.GetAsNullableString("id"); ok && id != "" {
criteria = append(criteria, "id='"+id+"'")
}
if name, ok := filter.GetAsNullableString("name"); ok && name != "" {
criteria = append(criteria, "name='"+name+"'")
}
if len(criteria) > 0 {
return strings.Join(criteria, " AND ")
} else {
return ""
}
}
func (c *MyIdentifiablePostgreSqlPersistence) GetPageByFilter(ctx context.Context, correlationId string,
filter data.FilterParams, paging data.PagingParams) (page data.DataPage[MyIdentifiableObject], err error) {
return c.IdentifiablePostgresPersistence.GetPageByFilter(ctx, correlationId,
c.composeFilter(filter), paging,
"", "",
)
}
import 'package:pip_services3_commons/pip_services3_commons.dart';
import 'package:pip_services3_postgres/pip_services3_postgres.dart';
class MyIdentifiableObject implements IIdentifiable<String> {
@override
String? id;
String key;
String name;
MyIdentifiableObject.from(this.id, this.key, this.name);
Map<String, dynamic> toJson() {
return <String, dynamic>{'id': id, 'key': key, 'name': name};
}
void fromJson(Map<String, dynamic> json) {
key = json['key'];
name = json['name'];
}
MyIdentifiableObject clone() {
return MyIdentifiableObject.from(id, key, name);
}
}
abstract class MyIdentifiablePersistence {
Future<DataPage<MyIdentifiableObject>> GetPageByFilter(
String? correlationId, FilterParams? filter, PagingParams? paging);
Future<MyIdentifiableObject?> create(
String? correlationId, MyIdentifiableObject? item);
Future<MyIdentifiableObject?> getOneById(String? correlationId, String id);
Future<MyIdentifiableObject?> deleteById(String? correlationId, String? id);
}
class MyIdentifiablePostgreSqlPersistence
extends IdentifiablePostgresPersistence<MyIdentifiableObject, String>
implements MyIdentifiablePersistence {
MyIdentifiablePostgreSqlPersistence() : super('mycollection', null);
String? composeFilter(FilterParams? filter) {
filter = filter ?? FilterParams();
var criteria = [];
var id = filter.getAsString('id');
if (id.isNotEmpty) {
criteria.add("id='" + id + "'");
}
var name = filter.getAsString('name');
if (name.isNotEmpty) {
criteria.add("name='" + name + "'");
}
return criteria.isNotEmpty ? criteria.join(' AND ') : null;
}
@override
Future<DataPage<MyIdentifiableObject>> GetPageByFilter(
String? correlationId, FilterParams? filter, PagingParams? paging) async {
return await super.getPageByFilter_(
correlationId, composeFilter(filter), paging, null, null);
}
}
from abc import ABC
from pip_services3_commons.data import IIdentifiable, FilterParams, PagingParams, DataPage
from pip_services3_postgres.persistence import IdentifiablePostgresPersistence
class MyIdentifiableObject(IIdentifiable):
def __init__(self, id: str = None, name: str = None, value: str = None):
self.id = id
self.name = name
self.value = value
class MyIdentifiablePersistence(ABC):
def get_page_by_filter(self, correlation_id: str, filter: FilterParams, paging: PagingParams) -> DataPage:
pass
def create(self, correlation_id: str, item: MyIdentifiableObject) -> MyIdentifiableObject:
pass
def get_one_by_id(self, correlation_id: str, id: str) -> MyIdentifiableObject:
pass
def delete_by_id(self, correlation_id: str, id: str) -> MyIdentifiableObject:
pass
class MyIdentifiablePostgreSqlPersistence(IdentifiablePostgresPersistence, MyIdentifiablePersistence):
def __init__(self):
super(MyIdentifiablePostgreSqlPersistence, self).__init__('mycollection')
def _compose_filter(self, filter_params: FilterParams):
filter_params = filter_params or FilterParams()
criteria = []
id = filter_params.get_as_string("id")
if id is not None and id != "":
criteria.append("id='" + id + "'")
name = filter_params.get_as_string("name")
if name is not None and name != "":
criteria.append("name='" + name + "'")
return None if len(criteria) < 0 else " AND ".join(criteria)
def get_page_by_filter(self, correlation_id: str, filter: FilterParams, paging: PagingParams) -> DataPage:
criteria = self._compose_filter(filter)
return super(MyIdentifiablePostgreSqlPersistence, self).get_page_by_filter(correlation_id, criteria, paging, None, None)
Most relational XyzIdentifiablePersistence
components have variations called XyzJsonIdentifiablePersistence
that store objects in JSON format. In this case, tables have only 2 fields: id and data. The id field contains the unique object Id and the data field contains the entire object data serialized as JSON:
CREATE TABLE MyIdentifiableJsonObject (
id VARCHAR(32) PRIMARY KEY,
data JSON
);
For more information, please, refer to the component documentation.
Custom Persistence
There are situations, when persistence has a complex data model, or there is already an existing implementation that does the work. In those cases, it is only necessary to use that implementation written in a chosen persistence framework and wrap it into a Pip.Services component to enable configuration and life-cycle management in order to place that persistence into a container and connect to other components in a data service. Here is a simple example of how it can be done.
import { ConfigParams, IConfigurable, IOpenable, IReferenceable, IReferences } from "pip-services3-commons-nodex";
class MyCustomPersistence {
// Custom implementation using any persistence framework
}
class MyCustomPersistenceWrapper implements IConfigurable, IReferenceable, IOpenable {
public _config: ConfigParams = new ConfigParams();
public _persistence: MyCustomPersistence;
public configure(config: ConfigParams): void {
// Store config parameters
this._config = config ?? this._config;
}
public setReferences(references: IReferences): void {
// Retrieve whatever references you may need
}
public isOpen(): boolean {
return this._persistence != null;
}
public async open(correlationId: string): Promise<void> {
if (this._persistence != null) return;
// Create custom persistence
this._persistence = new MyCustomPersistence();
// Configure custom persistence
...
// Open and connect to the database
await this._persistence.connect();
}
public async close(correlationId: string): Promise<void> {
if (this._persistence == null) return;
// Disconnect from the database and close
await this._persistence.disconnect();
this._persistence = null;
}
public customMethod(...) {
// Delegate operations to custom persistence
return await this._persistence.customMethod(...);
}
}
using System.Threading.Tasks;
using PipServices3.Commons.Config;
using PipServices3.Commons.Refer;
using PipServices3.Commons.Run;
class MyCustomPersistence
{
// Custom implementation using any persistence framework
}
class MyCustomPersistenceWrapper : IConfigurable, IReferenceable, IOpenable
{
public ConfigParams _config = new ConfigParams();
public MyCustomPersistence _persistence;
public void Configure(ConfigParams config)
{
// Store config parameters
this._config = config ?? this._config;
}
public void SetReferences(IReferences references)
{
// Retrieve whatever references you may need
}
public bool IsOpen()
{
return this._persistence != null;
}
public Task OpenAsync(string correlationId)
{
if (this._persistence != null) return;
// Create custom persistence
this._persistence = new MyCustomPersistence();
// Configure custom persistence
...
// Open and connect to the database
await this._persistence.connect();
}
public Task CloseAsync(string correlationId)
{
if (this._persistence == null) return;
// Disconnect from the database and close
await this._persistence.disconnect();
this._persistence = null;
}
public void CustomMethod(...)
{
// Delegate operations to custom persistence
return await this._persistence.customMethod(...);
}
}
import (
"context"
"github.com/pip-services3-go/pip-services3-commons-go/refer"
"github.com/pip-services3-gox/pip-services3-commons-gox/config"
)
type MyCustomPersistence struct {
// Custom implementation using any persistence framework
}
func NewMyCustomPersistence() *MyCustomPersistence {
return &MyCustomPersistence{}
}
type MyCustomPersistenceWrapper struct {
config *config.ConfigParams
persistence *MyCustomPersistence
}
func NewMyCustomPersistenceWrapper() *MyCustomPersistenceWrapper {
return &MyCustomPersistenceWrapper{
config: config.NewConfigParams(),
}
}
func (c *MyCustomPersistenceWrapper) Configure(ctx context.Context, config *config.ConfigParams) {
// Store config parameters
if config != nil {
c.config = config
}
}
func (c *MyCustomPersistenceWrapper) SetReferences(ctx context.Context, references refer.IReferences) {
// Retrieve whatever references you may need
}
func (c *MyCustomPersistenceWrapper) IsOpen() bool {
return c.persistence != nil
}
func (c *MyCustomPersistenceWrapper) Open(ctx context.Context, correlationId string) (err error) {
if c.persistence != nil {
return nil
}
// Create custom persistence
c.persistence = NewMyCustomPersistence()
// Configure custom persistence
// ...
// Open and connect to the database
c.persistence.Connect()
}
func (c *MyCustomPersistenceWrapper) Close(ctx context.Context, correlationId string) (err error) {
if c.persistence == nil {
return
}
// Disconnect from the database and close
c.persistence.Disconnect()
c.persistence = nil
}
import 'package:pip_services3_commons/pip_services3_commons.dart';
class MyCustomPersistence {
// Custom implementation using any persistence framework
}
class MyCustomPersistenceWrapper
implements IConfigurable, IReferenceable, IOpenable {
ConfigParams _config = ConfigParams();
MyCustomPersistence? _persistence;
@override
void configure(ConfigParams config) {
// Store config parameters
_config = config;
}
@override
void setReferences(IReferences references) {
// Retrieve whatever references you may need
}
@override
bool isOpen() {
return _persistence != null;
}
@override
Future open(String? correlationId) {
if (_persistence != null) {
return;
}
// Create custom persistence
_persistence = new MyCustomPersistence();
// Configure custom persistence
...
// Open and connect to the database
await _persistence.connect();
}
@override
Future close(String? correlationId) {
if (_persistence == null) {
return;
}
// Disconnect from the database and close
await _persistence.disconnect();
_persistence = null;
}
Future customMethod(...) async {
// Delegate operations to custom persistence
return await _persistence.customMethod(...);
}
}
from typing import Optional
from pip_services3_commons.config import IConfigurable, ConfigParams
from pip_services3_commons.refer import IReferenceable, IReferences
from pip_services3_commons.run import IOpenable
class MyCustomPersistence:
# Custom implementation using any persistence framework
pass
class MyCustomPersistenceWrapper(IConfigurable, IReferenceable, IOpenable):
def __init__(self):
self._config = ConfigParams()
self._persistence: MyCustomPersistence = None
def configure(self, config: ConfigParams):
# Store config parameters
self._config = config or self._config
def set_references(self, references: IReferences):
# Retrieve whatever references you may need
pass
def is_open(self) -> bool:
return self._persistence is not None
def open(self, correlation_id: Optional[str]):
if self._persistence is not None:
return
# Create custom persistence
self._persistence = MyCustomPersistence()
# Configure custom persistence
# ...
# Open and connect to the database
self._persistence.connect()
def close(self, correlation_id: Optional[str]):
if self._persistence is None:
return
# Disconnect from the database and close
self._persistence.disconnect()
self._persistence = None
def custom_method(self, ...):
# Delegate operations to custom persistence
return self._persistence.custom_method(...)
References
For more information about configurations see:
-
Config file syntax
-
Configurations
-
Component configuration
-
Configuring container
-
More about persistences