Exemplo Prático
Feature Experimental. Para acesso prévio envie email para [email protected] informando a appkey do seu projeto
Hello World
Este guia apresenta um exemplo simples para demonstrar a utilização de injeção de dependências, controle transacional, e a definição de entidades e repositórios, seguindo práticas de desenvolvimento modernas.
Configuração
Garanta que seu projeto esteja utilizando a versão 2.0.0 ou superior do SDK, conforme a configuração abaixo no seu arquivo build.gradle.
....
buildscript {
...
dependencies {
classpath "br.com.sankhya.studio:gradle-plugin:2+"
classpath "com.google.devtools.ksp:symbol-processing-gradle-plugin:2.0.20-1.0.24"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.0"
}
}
...
Componentes Principais
1. Entidade
As entidades agora são POJOs (Plain Old Java Objects) anotados, similar ao padrão JPA (Java Persistence API) utilizado em ecossistemas como o Spring. Essa abordagem permite o uso de tipos primitivos e tipos de data modernos, simplificando a manipulação de dados.
Lembre-se que as entidades precisam ser mapeadas no Dicionário de dados da plataforma.
import br.com.sankhya.studio.persistence.Column;
import br.com.sankhya.studio.persistence.Id;
import br.com.sankhya.studio.persistence.JapeEntity;
import lombok.Data;
@Data
@JapeEntity(entity = "Veiculo", table = "TGFVEI")
public class Veiculo {
@Id
@Column(name = "CODVEICULO")
private Long id;
@Column(name = "PLACA")
private String placa;
@Column(name = "ATIVO")
private Boolean ativo;
}
Tipos Suportados:
- Long/long
- Integer/int
- Boolean/boolean
- Float/float
- Double/double
- BigDecimal
- BigInteger
- String
- Timestamp
- LocalDate, LocalDateZone, LocalDateTime, LocalDateTimeZone
- Enums (devem possuir value).
2. Repositório
Para definir um repositório, crie uma interface que estenda JapeRepository
. O framework implementará automaticamente os métodos básicos de CRUD (save
, findById
, delete
, etc.) e as consultas que você definir.
É possível declarar consultas customizadas (criterias
) com parâmetros nomeados, seja pelo nome do argumento do método ou explicitamente com a anotação @Parameter
.
import br.com.sankhya.sdk.data.repository.JapeRepository;
import br.com.sankhya.studio.stereotypes.Repository;
@Repository
public interface VeiculoRepository extends JapeRepository<Long, Veiculo> {
@Criteria(clause="PLACA = :placa")
public Optional<Veiculo> findByPlaca(String placa);
@Criteria(clause="MODELO = :mod")
public List<Veiculo> findByModelo(@Parameter("mod") String modeloVeiculo);
}
- Retornos Flexíveis: Métodos podem retornar
Optional
, umPOJO
ou umaList
de objetos.
3. DTO (Data Transfer Object)
DTOs são objetos simples para transferir dados entre camadas (como da requisição para o serviço). Agora, eles suportam Java Bean Validation para validações automáticas e declarativas.
@Data
public class VeiculoDTO {
@NotBlank(message="Placa é requerido")
private String placa;
}
4. Serviço (Lógica de Negócio)
A camada de serviço contém a lógica de negócio da aplicação. Use a anotação @Component
e injete as dependências necessárias através do construtor.
A anotação @Transactional
garante que as operações no método sejam executadas dentro de uma única transação de banco de dados.
@Component
@RequiredArgsConstructor(onConstructor_ = @Inject) // Injeção via construtor com Lombok
public class VeiculoService {
private final VeiculoRepository veiculoRepository;
@Transactional
public void atualizar(String placa) throws Exception {
// 1. Busca a entidade no banco. 'veiculoDoBanco'
Veiculo veiculoDoBanco = veiculoRepository.findByPlaca(placa)
.orElseThrow(() -> new RuntimeException("Não encontramos um veículo com este ID."));
// 2. Modifica a entidade recuperada.
veiculoDoBanco.setAtivo(true);
// 3. Persiste a alteração e reatribui a variável.
Veiculo veiculoAtualizado = veiculoRepository.update(veiculoDoBanco);
// 4. Se precisarmos excluir em seguida, usamos a instância mais recente (veiculoAtualizado),
// que já possui o cache, tornando a operação de exclusão mais rápida.
veiculoRepository.delete(veiculoAtualizado);
}
}
5. Controller (Ponto de Entrada)
O Controller
expõe a funcionalidade como um serviço acessível externamente. Anote a classe com @Service
e defina um serviceName
para compor a URL de acesso.
As dependências (como o VeiculoService
) são injetadas no construtor.
@Service(serviceName = "VeiculoServiceSP")
public class VeiculoController {
private final VeiculoService veiculoService;
@Inject // Injeção de dependência via construtor
public VeiculoController(VeiculoService veiculoService) {
this.veiculoService = veiculoService;
}
@Transactional
public void atualizarEExcluirVeiculo(@Valid VeiculoDTO veiculo) throws Exception {
veiculoService.atualizar(veiculo.getPlaca());
}
}
- URL de Acesso: <endereço_servidor>/<nome_addon>/service.sbr?serviceName=VeiculoServiceSP.atualizarEExcluirVeiculo
Benefícios e Princípios de Desenvolvimento
Adotar esta arquitetura moderniza o desenvolvimento e traz benefícios significativos de organização, manutenibilidade e testabilidade, alinhando o código a princípios consolidados como Clean Code e SOLID.
Injeção de Dependências (ID)
- O que é? Em vez de uma classe criar suas próprias dependências (ex:
new VeiculoRepository()
), elas são "injetadas" de fora (pelo construtor, por exemplo). - Legibilidade e Clean Code: O construtor de uma classe declara explicitamente tudo o que ela precisa para funcionar. Isso torna as dependências claras e o código mais fácil de entender.
- Princípio da Inversão de Dependência (SOLID): A
VeiculoService
não depende da implementação concreta doVeiculoRepository
, mas sim de sua interface (abstração). Isso desacopla o código, permitindo que a implementação do repositório seja trocada sem impactar a lógica de negócio. - Testabilidade: Facilita a criação de testes unitários. É possível "mockar" (simular) o
VeiculoRepository
para testar aVeiculoService
de forma isolada, sem a necessidade de uma conexão real com o banco de dados.
Definição de Repositórios
- O que é? O Padrão de Repositório abstrai a camada de acesso a dados, tratando a fonte de dados como uma coleção de objetos.
- Legibilidade e Clean Code: Centraliza toda a lógica de acesso a dados em um único lugar (a interface do repositório). A camada de serviço (
VeiculoService
) apenas utiliza métodos comofindByPlaca
, sem precisar se preocupar com a construção de queries SQL ou com a forma como os dados são persistidos. - Princípio da Responsabilidade Única (SOLID): O repositório tem uma única responsabilidade: gerenciar a persistência da entidade
Veiculo
. A classe de serviço tem outra: orquestrar a lógica de negócio. Essa separação de preocupações é a base de uma arquitetura limpa e organizada, tornando o código mais fácil de manter e escalar.
Updated about 17 hours ago