123 lines
4.0 KiB
Plaintext
123 lines
4.0 KiB
Plaintext
export const metadata = {
|
||
title: `${pageNumber} Database Operations in Service Methods`,
|
||
}
|
||
|
||
# {metadata.title}
|
||
|
||
In this document, you’ll learn how to implement database operations, such as creating a record, in a service’s methods.
|
||
|
||
## Transaction Manager
|
||
|
||
A transaction wraps a set of database operations to ensure that when an error occurs, all database changes made by the executed operations are rolled back.
|
||
|
||
When you implement a method in your service, you must add the `@InjectTransactionManager` decorator to the method performing database operations. For example:
|
||
|
||
```ts title="src/modules/hello/service.ts" highlights={[["26"]]}
|
||
// other imports
|
||
import { InjectTransactionManager } from "@medusajs/utils"
|
||
import { DAL } from "@medusajs/types"
|
||
|
||
type InjectedDependencies = {
|
||
baseRepository: DAL.RepositoryService
|
||
myCustomService: ModulesSdkTypes.InternalModuleService<any>
|
||
}
|
||
|
||
class HelloModuleService extends ModulesSdkUtils
|
||
.abstractModuleServiceFactory<
|
||
// ...
|
||
>(
|
||
// ...
|
||
) {
|
||
protected baseRepository_: DAL.RepositoryService
|
||
|
||
constructor(
|
||
{ baseRepository }: InjectedDependencies
|
||
) {
|
||
// @ts-ignore
|
||
super(...arguments)
|
||
this.baseRepository_ = baseRepository
|
||
}
|
||
|
||
@InjectTransactionManager("baseRepository_")
|
||
async create(
|
||
// TODO add parameters
|
||
) {
|
||
// TODO add implementation
|
||
}
|
||
}
|
||
```
|
||
|
||
The `@InjectTransactionManager` decorator accepts as a parameter the name of the service class field to inject the transaction manager to, which is the `baseRepository_` field.
|
||
|
||
---
|
||
|
||
## Generated Service Methods
|
||
|
||
As mentioned in a previous chapter, when you use the container loader factory to register resources in your module’s container, the factory creates a service for each data model you specify and registers it in the container. The registration name is the camel-case name of the data model with `Service` appended to it.
|
||
|
||
So, the container loader factory creates a `myCustomService` for the `MyCustom` data model.
|
||
|
||
These generated services already implement data-management methods such as `create` or `update`. So, in your module’s service, you can resolve the generated service and use it to create a record.
|
||
|
||
For example:
|
||
|
||
export const highlights = [
|
||
["13", "", "Inject myCustomService, which is the service generated by the container loader for the MyCustom data model."],
|
||
["23", "", "Add a new field for the generated service of the MyCustom data model."],
|
||
["31", "", "Set the class field to the injected dependency."],
|
||
["39", "create", "Use the `create` method of the generated service."]
|
||
]
|
||
|
||
```ts title="src/modules/hello/service.ts" highlights={highlights}
|
||
// other imports...
|
||
import { ModulesSdkTypes } from "@medusajs/types"
|
||
import { MyCustom } from "./models/my-custom"
|
||
|
||
// ...
|
||
|
||
type CreateMyCustomDTO = {
|
||
name: string
|
||
}
|
||
|
||
type InjectedDependencies = {
|
||
baseRepository: DAL.RepositoryService
|
||
myCustomService: ModulesSdkTypes.InternalModuleService<any>
|
||
}
|
||
|
||
class HelloModuleService extends ModulesSdkUtils
|
||
.abstractModuleServiceFactory<
|
||
// ...
|
||
>(
|
||
// ...
|
||
) {
|
||
protected baseRepository_: DAL.RepositoryService
|
||
protected myCustomService_: ModulesSdkTypes.InternalModuleService<MyCustom>
|
||
|
||
constructor(
|
||
{ baseRepository, myCustomService }: InjectedDependencies
|
||
) {
|
||
// @ts-ignore
|
||
super(...arguments)
|
||
this.baseRepository_ = baseRepository
|
||
this.myCustomService_ = myCustomService
|
||
}
|
||
|
||
@InjectTransactionManager("baseRepository_")
|
||
async create(
|
||
data: CreateMyCustomDTO,
|
||
@MedusaContext() context: Context = {}
|
||
): Promise<MyCustomDTO> {
|
||
const myCustom = await this.myCustomService_.create(
|
||
data,
|
||
context
|
||
)
|
||
|
||
return myCustom
|
||
}
|
||
}
|
||
```
|
||
|
||
In the above example, you add `myCustomService` to the `InjectedDependencies` type to resolve the service in the constructor and set it in a class field.
|
||
|
||
In the `create` method, you use `myCustomService`'s `create` method to create the record. You pass it the record’s data as a first parameter, and the Medusa application’s context as a second parameter.
|