Hello Simon,
thx for answering!
sounds good, i think i will go this way.
Java-Records are really nice / concise and also have toString, equals, hashCode which can also be helpful.
I see two ways where the projection can be build with:
- a) ... on the Jooq-Records (Jooq-Record Classes generated by Codegen)
- b) ... directly on the Jooq DSL
i think you have meant b) in your example. And i will also go that way i think,
Sometimes it can also be good to go with a) because then at least Bulk/Batch Inserts and similar performance-optimizations can be done in an AbstractDAO for the inserts.
But b) is simpler (has less code-parts / more concise)
Here an example for a) and for a REST Create Endpoint.
Each endpoint would have individual DTOs for Reqest/Response, as defined by CQRS.
---
ProductControllerV1
public CreateProductResponseV1 create(CreateProductRequestV1 createProductRequest) throws ValidationException {
return productManager.create(new RequestContext(1, 1), createProductRequest);
}
---
ProductManagerV1
public CreateProductResponseV1 create(RequestContext requestContext, final CreateProductRequestV1 createProductRequest) throws ValidationException {
return database1.dsl(requestContext).transactionResult(tsx -> {
ProductDAOV1 productDAOV1 = new ProductDAOV1(tsx.dsl());
this.validate(createProductRequest);
// request-dto to jooq-record projection
ProductRecord insert = new ProductRecord();
insert.setClientId(createProductRequest.clientId());
insert.setPrice(createProductRequest.price());
insert.setTypeId(createProductRequest.typeId());
insert.setDeleted(false);
productDAOV1.insert(insert);
ProductRecord result = productDAOV1.fetch(insert.getProductId());
// jooq-record to response-dto projection
return new CreateProductResponseV1(
result.getProductId(),
result.getClientId(),
result.getPrice(),
result.getTypeId(),
result.getCreatedAt(),
result.getUpdatedAt(),
result.getDeleted(),
result.getCreatorId()
);
});
}
---
CreateProductRequestV1
public record CreateProductRequestV1(
@NotNull Integer clientId,
@NotNull BigDecimal price,
@NotNull @Size(max = 255) String typeId
) {
}
---
CreateProductResponseV1
public record CreateProductResponse(
@NotNull Long productId,
@NotNull Integer clientId,
@NotNull BigDecimal price,
@NotNull @Size(max = 255) String typeId,
@NotNull LocalDateTime createdAt,
@NotNull LocalDateTime updatedAt,
@NotNull Boolean deleted,
@NotNull Integer creatorId
) {
}
---
additional, if the DAO is used for the projection (like you suggested) the DAO insert-method could look like this,
for example:
ProductDAOV1
public class ProductDAOV1 extends AbstractDAO<ProductRecord, Long> {
...
int insertProduct(CreateProductRequestV1 createProductRequest) {
return dsl()
.insertInto(PRODUCT)
.set(PRODUCT.CLIENTID, createProductRequest.clientId())
.set(PRODUCT.PRICE, createProductRequest.price())
.set(PRODUCT.TYPEID, createProductRequest.typeId())
.set(PRODUCT.DELETED, false)
.execute();
}