Fundo
Procurando passar um conjunto de pares de nome/valor para um procedimento armazenado de maneira independente do banco de dados, usando JDBC. Uma estrutura de banco de dados é definida da seguinte forma:
CREATE TYPE array_parameters AS (
v_name VARCHAR2(255),
v_value CLOB
);
Essa estrutura, que pode ter definições equivalentes na maioria dos bancos de dados relacionais modernos, está sendo proposta como uma forma de passar um número arbitrário de pares nome/valor para um procedimento armazenado. A chamada do procedimento armazenado é semelhante a:
SELECT rxm( '...map...', array_parameters );
Onde o ...map...
pode incluir qualquer número de referências variáveis, assumindo a seguinte forma :
account.id = $id &&
person.last_name = $surname && ...
O array_parameters
, em teoria, poderia ser preenchido como:
array_parameters[0].v_name = "$id";
array_parameters[0].v_value = "123456789";
array_parameters[1].v_name = "$surname";
array_parameters[1].v_value = "O'Malley, The \"Great\"";
Problema
JDBC4 define um método chamado createArrayOf , que é o New South China Mall of APIs:
- Não suportado pela Oracle
- Não suportado pelo MySQL
- Não suportado pelo Microsoft SQL Server
- Não suportado pelo Apache Derby
- Sem suporte da Sybase
Sem a capacidade de criar a matriz de par de nome/valor, não vejo nenhuma maneira óbvia de passar os valores sem recorrer a implementações específicas do banco de dados (como usar o ARRAY da Oracle ou contorções obtusas para oferecer suporte ao MySQL).
Pergunta
Como você definiria e, em seguida, chamaria um procedimento armazenado que pode receber um número arbitrário de pares nome/valor de maneira independente do banco de dados?
Ideia #1
Uma ideia seria definir duas matrizes de strings, em vez de uma estrutura de matriz de objeto, e chamar o procedimento armazenado da seguinte maneira:
SELECT rxm( '...map...', array_names, array_values );
As duas matrizes seriam vinculadas a índices, mas isso provavelmente createArrayOf()
também dependeria de .
Ideia #2
Pode ser possível passar os pares como strings separadas por vírgulas. No entanto, os próprios valores podem conter vírgulas, o que dificulta a codificação de parâmetros usando strings separadas por vírgula. (Falando de modo geral, qualquer separador pode aparecer como um caractere em algum lugar nos valores, o que também inclui separadores de escape, como \,
.)
Essa parece ser a solução mais independente de banco de dados, mas implementar uma rotina de decodificação CSV em vários bancos de dados em PL/SQL não é trivial nem eficiente.
Ideia #3
Use o Hibernate como uma camada de abstração e implemente uma rotina JPQL que passa na matriz de pares nome/valor. Por exemplo, chamar query.setParameterList , que pode funcionar apenas para IN
cláusulas, em vez de parâmetros de procedimentos armazenados.
Passe os valores como XML (em um VARCHAR). O banco de dados a seguir oferece suporte à fragmentação de XML da linguagem de consulta:
Obviamente, nem todos os bancos de dados obscuros do planeta o suportam. Mas os acima são realisticamente os únicos com os quais você precisa se preocupar para atingir 99,9% do mercado de banco de dados.
Outra possibilidade:
Base64 não codifica nenhuma vírgula em seu conjunto de caracteres padrão e é ou parece ser suportado por:
Observe que, para o SQL Server, não há suporte para texto codificado em UTF-8, portanto, UTF-16 deve ser usado. Isso depende da funcionalidade básica de divisão de strings, que é razoavelmente onipresente.