AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Repository

skill-snk-devcenter-addon-studio-repository · by snk-devcenter

Cria, revisa e refatora interfaces `@Repository` Sankhya estendendo `JapeRepository<ID, Entity>` com `@Criteria`, `@NativeQuery`, `@Modifying`, `@Parameter(name = "...")`, paginação, `findByPK` (retorno nullable, `throws Exception`). Use ao criar, alterar, revisar, auditar ou padronizar a camada de acesso a dados, ao implementar consulta/listagem/filtro/paginação/busca, ao escrever query custom,…

No reviews yet
0 installs
5 views
0.0% view→install

Install

$ agentstack add skill-snk-devcenter-addon-studio-repository

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-snk-devcenter-addon-studio-repository)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
13d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Repository? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Repositório (@Repository) — Addon Studio 2.0

Padrão Repository no SDK Sankhya = abstração simplifica acesso dados. Define interfaces declarativas, SDK gera implementação em compile-time — sem boilerplate, type-safe, protege SQL Injection.

> Referência complementar: consulte entity para criar entidades correspondentes.


1. Criando um Repositório

Repositório = interface que estende JapeRepository:

import br.com.sankhya.sdk.data.repository.JapeRepository;
import br.com.sankhya.studio.stereotypes.Repository;

@Repository
public interface VeiculoRepository extends JapeRepository {
    // métodos customizados aqui
}
  • BigDecimal → tipo chave primária (primeiro param). PK de tabela nativa Sankhya = BigDecimal; PK de tabela do addon = Integer (ver entity)
  • Veiculo → classe entidade (segundo param)

2. Métodos CRUD Padrão (Herdados)

| Método | Descrição | Lança | |:-----------------------------|:----------------------------------------------------------------------------|:------------| | save(T entity) | Salva ou atualiza entidade | Exception | | findByPK(ID id) | Busca por PK → retorna T (pode ser null — verificar com null-check) | Exception | | findAll() | Retorna todas instâncias | Exception | | findAll(Pageable pageable) | Retorna página com ordenação → Page | Exception | | delete(T entity) | Remove entidade do banco | Exception |

> Atenção: todos os métodos herdados lançam Exception checked. Todo método de serviço ou controller que os chame deve declarar throws Exception na assinatura. > > findByPK retorna T (nullable), não Optional. Use null-check manual: > ``java > MinhaEntidade e = repository.findByPK(id); > if (e == null) throw new MinhaException("Registro não encontrado: " + id); > ``


3. Consultas Customizadas

3.1 @Criteria — Consultas com Condição WHERE

Use @Criteria para filtros SELECT simples tipados.

Obrigatório: prefixo this. em todos campos da clause.


@Criteria(clause = "this.PLACA = :placa")
Optional findByPlaca(String placa);

@Criteria(clause = "this.ATIVO = :ativo")
List findByAtivo(Boolean ativo);

@Criteria(clause = "this.CODEMP = :empresa AND this.STATUS = :status")
List findByEmpresaAndStatus(BigDecimal empresa, String status);

> Quando usar @Parameter: > > - Opcional quando o nome do parâmetro Java casa com o :nome da clause — basta declarar BigDecimal empresa, String status (vincula automaticamente). > - Obrigatório quando os nomes diferem. Sintaxe correta: @Parameter(name = "...") — sempre com name = explícito. A forma posicional @Parameter("...") causa erro de compilação.

// Nome do parâmetro Java != :nome da clause → @Parameter(name = "...") obrigatório
@Criteria(clause = "this.DTNEG BETWEEN :dataInicio AND :dataFim")
List findByPeriodo(
    @Parameter(name = "dataInicio") java.sql.Date inicio,
    @Parameter(name = "dataFim") java.sql.Date fim
);
Operadores SQL suportados em @Criteria

| Operador / construção | Exemplo de clause | |:----------------------------------------|:--------------------------------------------------------------| | Comparação (=, >, =, = :valor | | LIKE | this.PLACA LIKE :prefix | | IN com List | this.CODPROD IN (:codigos) (parâmetro List codigos) | | BETWEEN | this.DTNEG BETWEEN :inicio AND :fim | | IS NULL / IS NOT NULL | this.DHCONFIRMACAO IS NULL | | Funções SQL (UPPER, LOWER, CONCAT, COUNT, SUM) | UPPER(this.NOMEPARC) = UPPER(:nome) | | Macros Sankhya portáveis | this.DTMOV = dbDate(), ignorecase(this.NOME) = ignorecase(:nome) |

> Macros são preferidas à sintaxe específica de banco (SYSDATE, NVL, ||, ROWNUM). Ver skill macros para o catálogo completo.


3.2 @NativeQuery — Consultas SQL Nativas

> Import obrigatório: import br.com.sankhya.studio.persistence.NativeQuery; > Cobre tanto @NativeQuery quanto @NativeQuery.Result. Não usar br.com.sankhya.sdk.data.repository.NativeQuery — pacote incorreto, causa erro de compilação.

Use @NativeQuery para queries complexas com JOINs, agregações, funções específicas banco etc.


@NativeQuery("SELECT CODVEICULO, PLACA FROM TGFVEI WHERE MODELO = :modelo")
List findByModeloNativo(String modelo);
Mapeando o resultado com @NativeQuery.Result

Crie interface anotada com @NativeQuery.Result para mapear colunas retornadas:


@NativeQuery.Result
interface VeiculoDTO {

    BigDecimal getCodVeiculo();   // mapeia coluna CODVEICULO

    String getPlaca();      // mapeia coluna PLACA
}

Nomes dos getters devem coincidir exatamente com nomes/aliases das colunas. Divergência = null.

Retornando tipos Java simples

@NativeQuery("SELECT DESCRPROD FROM TGFPRO WHERE CODPROD = :codigo")
String buscarDescricaoPorCodigo(BigDecimal codigo);

@NativeQuery("SELECT COUNT(1) FROM TGFPRO")
Long contarTotalDeProdutos();

Queries tipo simples devem retornar exatamente uma coluna. Mais de uma lança ResultHasMoreThanOneColumnException.

Passando JdbcWrapper para reuso de conexão

Ideal dentro de @Listener, reaproveita conexão transacional existente:


@NativeQuery("SELECT COUNT(1) FROM TGFCAB WHERE STATUS = 'P'")
Long contarPendentes(JdbcWrapper jdbc);

3.3 @Modifying + @NativeQuery — Operações de Escrita (UPDATE / DELETE / INSERT)


@Modifying
@NativeQuery("UPDATE TGFPRO SET VLRVENDA = VLRVENDA * :fator WHERE CODGRUPOPROD = :grupo")
void reajustarPrecoPorGrupo(BigDecimal fator, BigDecimal grupo);

@Modifying
@NativeQuery("DELETE FROM TDCXYZLOG WHERE DTEXPIRACAO  **`@Modifying` deve retornar `void` ou `Boolean`.** KSP rejeita `int` com erro de compilação.

Sempre envolva `@Modifying` em método `@Transactional`.

```java

@Transactional
public void limparLogsAntigos(java.sql.Date data) throws Exception {
    logRepository.excluirLogsExpirados(data);
}

3.4 Paginação com @Criteria

Paginação suportada apenas com @Criteria. @NativeQuery não suporta.


@Criteria(clause = "this.ATIVO = :ativo")
Page findByAtivoPaginado(Boolean ativo, Pageable pageable);

Uso no serviço:

PageRequest pageRequest = PageRequest.of(0, 10, Sort.by("PLACA", Direction.DESC));
Page pagina = repository.findByAtivoPaginado(true, pageRequest);

3.5 Funções SQL e Macros Sankhya

// Macro dbDate() — data/hora atual do banco (portatil Oracle/MSSQL)
@Criteria(clause = "this.DTMOV = dbDate()")
List findByDataAtual();

// Macro ignorecase() — busca tolerante a case e acentos
@Criteria(clause = "ignorecase(this.NOMEPARC) = ignorecase(:nome)")
List findByNomeParceiro(String nome);

// Macro nullValue() — substitui null por padrao (NVL/ISNULL portatil)
@NativeQuery("SELECT nullValue(VLRDESCONTO, 0) FROM TGFCAB WHERE NUNOTA = :nu")
BigDecimal descontoOuZero(BigDecimal nu);

> Macros traduzem automaticamente entre Oracle e MSSQL. Lista completa (datas, texto, conversoes, agregacoes): ver macros. Sempre prefira macro a sintaxe especifica de banco (SYSDATE, NVL, ||, ROWNUM, etc.).


3.6 Entidade com Chave Primária Composta (@Embeddable)


@Embeddable
public class ItemNotaPK {

    @Column(name = "NUNOTA")
    private BigDecimal numeroUnico;
    @Column(name = "SEQUENCIA")
    private BigDecimal sequenciaItem;
}

@JapeEntity(entity = "ItemNota", table = "TGFITE",
            isNativeTable = true, isNativeInstance = true)
public class ItemNota {

    @Id
    private ItemNotaPK id;
    @Column(name = "CODPROD")
    private BigDecimal codProduto;
}

@Repository
public interface ItemNotaRepository extends JapeRepository {
    // CRUD para chave composta funciona automaticamente
}

3.7 ResultSetMethods — Desambiguação de Tipo Simples

Quando @NativeQuery retorna tipo Java simples (String, Long, etc.) e o ResultSet tem múltiplos métodos compatíveis (ex.: getString vs getNString), use o atributo method para forçar a leitura específica:

import br.com.sankhya.studio.persistence.NativeQuery;
// ResultSetMethods e enum ANINHADO em NativeQuery — sem import proprio; use NativeQuery.ResultSetMethods

@NativeQuery(value = "SELECT DESCRICAO FROM TGFPRO WHERE CODPROD = :codigo",
             method = NativeQuery.ResultSetMethods.GET_N_STRING)
String buscarDescricaoNVarchar(BigDecimal codigo);

> Caso típico: colunas NVARCHAR/NCHAR (Unicode) no MSSQL exigem getNString para preservar caracteres multi-byte. Sem o method, o SDK chama getString por padrão.


3.8 ParamMatrix — Tuplas Múltiplas em IN

Quando o filtro envolve múltiplas colunas combinadas (ex.: (CODEMP, CODFIL) IN ((1,1), (1,2), (2,3))), use ParamMatrix no parâmetro:

import br.com.sankhya.sdk.data.structures.ParamMatrix;
import java.math.BigDecimal;
import java.util.Arrays;

ParamMatrix matrix = ParamMatrix.of(
    Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(1)),   // (CODEMP=1, CODFIL=1)
    Arrays.asList(BigDecimal.valueOf(1), BigDecimal.valueOf(2)),   // (CODEMP=1, CODFIL=2)
    Arrays.asList(BigDecimal.valueOf(2), BigDecimal.valueOf(3))    // (CODEMP=2, CODFIL=3)
);

List filiais = filialRepository.findByEmpresaFilial(matrix);
Sintaxe diverge entre Oracle e MSSQL
-- Oracle aceita IN com tuplas direto:
(CODEMP, CODFIL) IN (:matrix)

-- MSSQL não aceita; precisa EXISTS + VALUES:
EXISTS (SELECT 1 FROM (VALUES :matrix) AS T(CODEMP, CODFIL)
        WHERE T.CODEMP = TGFFIL.CODEMP AND T.CODFIL = TGFFIL.CODFIL)

> Recomendação: sempre que usar ParamMatrix, externalize a query em arquivo XML multi-banco (` + ) — não dá pra escrever uma única clause portável. Ver seção 4. Queries SQL Externas`.

@NativeQuery(value = "queries/filiais-por-tupla.xml", fromFile = true)
List findByEmpresaFilial(ParamMatrix matrix);

    
        SELECT * FROM TGFFIL WHERE (CODEMP, CODFIL) IN (:matrix)
    
    
        SELECT TGFFIL.* FROM TGFFIL
        WHERE EXISTS (
            SELECT 1 FROM (VALUES :matrix) AS T(CODEMP, CODFIL)
            WHERE T.CODEMP = TGFFIL.CODEMP AND T.CODFIL = TGFFIL.CODFIL
        )
    

4. Queries SQL Externas (Arquivos)

Queries complexas (100+ linhas) = arquivos externos com fromFile = true.

Arquivo .sql (compatível Oracle e MSSQL)


@NativeQuery(value = "queries/listar-veiculos-ativos.sql", fromFile = true)
List listarAtivos(String ativo);

Arquivo: model/src/main/resources/queries/listar-veiculos-ativos.sql

SELECT v.CODVEI, v.PLACA, v.DESCRICAO
FROM TGFVEI v
WHERE v.ATIVO = :ativo
ORDER BY v.DESCRICAO

Arquivo .xml (queries por banco de dados)

Use quando sintaxe difere entre Oracle e MSSQL:

Arquivo: model/src/main/resources/queries/quantidade-vendida.xml


    
        
        SELECT COUNT(*) FROM TGFCAB
    
    
        SELECT NVL(SUM(ITE.QTDNEG), 0) AS TOTAL FROM TGFITE ITE
        WHERE ITE.CODPROD = :codProd
    
    
        SELECT ISNULL(SUM(ITE.QTDNEG), 0) AS TOTAL FROM TGFITE ITE
        WHERE ITE.CODPROD = :codProd
    

Prioridade de seleção:

  1. `` — usada para ambos bancos (maior prioridade)
  2. ` ou — só se ` vazia

Queries de arquivos cacheadas automaticamente em memória após primeira leitura.


Validações em Compile-Time

SDK valida queries externas durante compilação:

| Verificação | Resultado | |:------------------------------------|:-------------------| | Arquivo não encontrado | Erro de compilação | | Arquivo .sql vazio | Erro de compilação | | XML mal formado | Erro de compilação | | Todas as tags XML vazias | Erro de compilação | | Apenas Oracle OU MSSQL definida | Warning | | Parâmetros inconsistentes entre DBs | Erro de compilação |


5. Boas Práticas

  1. Use Optional para resultados de @Criteria que podem não existir. Para findByPK, o retorno é T (nullable) — use null-check manual
  2. Nomes descritivos — prefira findByPlaca a genérico buscar
  3. Valide params no serviço antes de chamar repositório
  4. Separe responsabilidades — lógica de negócio no service (@Component), não no repositório
  5. Use @Transactional para toda operação @Modifying
  6. Evite SELECT * — mapeie só campos necessários
  7. Use paginação para consultas com muitos registros (padrão: 500 por sessão)
  8. Prefira `` em XMLs para query única entre bancos

6. Anti-Patterns

// Errado: query genérica sem filtros — pode retornar muitos registros
@Criteria(clause = "1 = 1")
List findAll();

// Correto: sempre use filtros obrigatórios
@Criteria(clause = "this.ATIVO = 'S' AND this.CODEMP = :empresa")
List findAtivosByEmpresa(BigDecimal empresa);

// Errado: lógica de negócio dentro do repositório
@Repository
public interface PedidoRepository extends JapeRepository {

    default void aprovarPedido(BigDecimal nunota) { /* ... */ }
}

// Correto: lógica de negócio no serviço
@Component
public class PedidoService {

    @Transactional
    public void aprovarPedido(BigDecimal nunota) throws Exception {
        Pedido pedido = repository.findByPK(nunota);
        if (pedido == null) throw new IllegalArgumentException("Pedido não encontrado: " + nunota);
        repository.save(pedido);
    }
}

// Errado: query methods do Spring Data NÃO são suportados
List findByPlacaStartingWith(String prefix); // não funciona

// Correto: use @Criteria no lugar
@Criteria(clause = "this.PLACA LIKE :prefix")
List findByPlacaStartingWith(String prefix);

7. Limitações Conhecidas

  • Query Methods por nome (estilo Spring Data JPA) não suportados
  • Paginação só com @Criteria, não com @NativeQuery
  • Limite padrão registros: 500 por sessão (use paginação pra contornar)
  • @Delete descontinuada — use @Modifying + @NativeQuery para exclusões

8. Exemplo Completo

// Entidade (tabela e instância nativas — flags + Lombok obrigatórios, ver `entity` §1.2)
@Data
@NoArgsConstructor
@AllArgsConstructor
@JapeEntity(entity = "CabecalhoNota", table = "TGFCAB",
            isNativeTable = true, isNativeInstance = true)
public class Pedido {

    @Id
    @Column(name = "NUNOTA")
    private BigDecimal numero;
    @Column(name = "CODPARC")
    private BigDecimal codigoCliente;
    @Column(name = "VLRNOTA")
    private BigDecimal valor;
    @Column(name = "STATUS")
    private String status;
    @Column(name = "DHALTER")
    private Timestamp dataAlteracao;
}

// DTO de resultado
@NativeQuery.Result
public interface PedidoResumoDTO {

    BigDecimal getNumero();

    BigDecimal getValor();
}

// Repositório
@Repository
public interface PedidoRepository extends JapeRepository {

    @Criteria(clause = "this.CODPARC = :codigoCliente")
    List findByCliente(BigDecimal codigoCliente);

    @NativeQuery("SELECT NUNOTA as numero, VLRNOTA as valor FROM TGFCAB WHERE STATUS = :status AND CODEMP = :empresa")
    List findResumoPorStatus(
        String status,
        BigDecimal empresa
    );

    @Modifying
    @NativeQuery("DELETE FROM TGFCAB WHERE STATUS = 'R' AND DHALTER  busc

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [snk-devcenter](https://github.com/snk-devcenter)
- **Source:** [snk-devcenter/addon-studio](https://github.com/snk-devcenter/addon-studio)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.