Transformando resultados JDBC para JSON de forma eficiente
1. Transformando eficientemente
resultados de uma consulta
JDBC para JSON
Vamos enfrentá-lo: JSON é o formato de saída dominante para os
serviços mais RESTful. Então, o que é uma maneira fácil de
converter seus resultados SQL para este formato popular? Leia
mais para descobrir como.
Um monte de dados da empresa são armazenados em bancos de
dados relacionais e acessado através de consultas SQL. Muitos
serviços web são pouco mais do que invólucros com base em
HTTP em torno de tais consultas.
Infelizmente, transformando os resultados da consulta para JSON
para que ele possa ser consumido por um aplicativo cliente muitas
vezes envolve numerosos passos ineficientes, tais como ligação
cada linha para um objeto de dados e carregar todos os dados na
memória antes de serialização-lo de volta para o chamador. Este
tipo de abordagem tem um impacto negativo no desempenho e
scalabilty. Cada linha requer múltiplas alocações de heap e
invocações do construtor, aumentando a latência e carga da CPU.
Pior, o chamador não receber uma resposta até que todo o
conjunto de dados foi processada.
Além disso, uma vez que cada resposta é carregado
completamente na memória, aplicações de grande volume
requerem uma grande quantidade de RAM, e só pode ser
dimensionado através da adição de hardware mais física.
Eventualmente, o coletor de lixo tem que correr, retardando todo
o sistema.
Uma abordagem muito mais eficiente é para transmitir dados de
resposta. Em vez de copiar os resultados da consulta em uma
estrutura de dados na memória antes de enviar a resposta, o
serviço web pode escrever uma linha de dados para o fluxo de
saída cada vez que uma linha é lida a partir do conjunto de
resultados. Isto permite a um cliente para começar a receber os
2. dados assim que ele estiver disponível, reduzindo
significativamente a latência. Além disso, porque há estruturas de
dados são criadas intermédias, CPU e memória de carga é
reduzida, permitindo que cada servidor para lidar com maior
número de pedidos simultâneos. Finalmente, porque menos
alocações de heap são necessários, o coletor de lixo precisa ser
executado com muito menos frequência, resultando em menos
pausas do sistema.
Introducing HTTP-RPC
HTTP-RPC é um framework open-source para simplificar o
desenvolvimento de aplicativos baseados em REST. Ele permite
aos desenvolvedores criar e de acesso com base em HTTP serviços
web usando uma RPC-como metáfora conveniente, preservando
princípios fundamentais de REST como apatridia e acesso a
recursos uniforme. O projeto atualmente inclui suporte para a
implementação de serviços REST em Java e consumo de serviços
em Java, Objective-C / Swift, ou JavaScript.
serviços HTTP-RPC são acessados através da aplicação de um
verbo HTTP como GET ou POST para um recurso de destino.
Argumentos são fornecidos quer através da cadeia de consulta ou
no corpo da solicitação, como um formulário HTML. Os
resultados são geralmente retornado como JSON, apesar de as
operações que não retornam um valor também são suportados.
Por exemplo, a sequência do pedido pode recuperar a soma de
dois números, cujos valores são especificados pelos argumentos a
e b de consulta:
GET /math/sum?a=2&b=4
O serviço iria retornar o valor 6 em resposta.
WebService Class
WebService é uma classe base abstrata para serviços web HTTP-
RPC. operações de serviço são definidos pela adição de métodos
públicos para a implementação do serviço concreto.
3. A anotação @RPC é usado para marcar um método como acessível
remotamente. Esta anotação associa um verbo HTTP e um
caminho de recursos com o método. Todos os métodos públicos
anotada automaticamente tornam-se disponíveis para a execução
remota de quando o serviço é publicado.
Por exemplo, a seguinte classe pode ser utilizada para
implementar a operação de adição simples discutidos na secção
anterior:
public class MathService extends WebService {
@RPC(method="GET", path="sum")
public double getSum(double a, double b) {
return a + b;
}
}
Argumentos pode ser qualquer tipo primitivo numérico,
booleano, String, java.net.URL ou java.util.List. Argumentos
de URL representam conteúdo binário e só pode ser usado
com solicitações POST. os argumentos da lista pode ser
usado com qualquer tipo de solicitação, mas os elementos da
lista deve ser um tipo simples suportado; por exemplo. List
<Double> orList <URL>.
Os métodos podem retornar qualquer tipo primitivo
numérico, booleano, CharSequence, java.util.List ou
java.util.Map. Os resultados são mapeados para os seus
equivalentes JSON como se segue:numeric primitive:
number
boolean: true/false
CharSequence: string
java.util.List: array
java.util.Map: object
Métodos também pode retornar nulo para indicar que eles não
produzem um valor.
Lista e mapear tipos não são obrigados a apoiar o acesso aleatório;
iteratividade é suficiente. Isso permite que implementações de
serviço para transmitir dados de coleção em vez de buffer na
memória antes de serem gravados. Além disso, tipos de coleção
que implementam a interface AutoCloseable será fechado
automaticamente após o seu conteúdo ter sido escrito para o fluxo
de saída, garantindo que os recursos do sistema não são
divulgados.
4. ResultSetAdapter Class
A classe ResultSetAdapter permite que o resultado de uma
consulta SQL para ser eficientemente retornado de um método de
serviço. Essa classe implementa a interface List e faz com que cada
linha em um conjunto de resultados JDBC aparecer como uma
instância de Mapa, tornando os dados adequados para
serialização JSON. Também implementsAutoCloseable, para
garantir que o conjunto de resultados subjacente é fechado uma
vez que todos os dados de resposta foi escrito.
Além disso, ResultSetAdapter é só para a frente de rolagem; seu
conteúdo, não são acessíveis através do () métodos andsize get ().
Isto permite que os resultados da consulta para ser devolvida ao
chamador directamente, sem qualquer intermediário de
tamponamento.
Por exemplo, considere um serviço web que retorna o resultado de
uma consulta SQL nesta mesa, tomadas a partir da base de dados
exemplo BIRT:
CREATE TABLE Products (
productCode VARCHAR(50) NOT NULL,
productName VARCHAR(70) NOT NULL,
productLine VARCHAR(50) NOT NULL,
productScale VARCHAR(10) NOT NULL,
productVendor VARCHAR(50) NOT NULL,
productDescription TEXT NOT NULL,
quantityInStock SMALLINT NOT NULL,
buyPrice DOUBLE NOT NULL,
MSRP DOUBLE NOT NULL,
PRIMARY KEY (productCode)
);
O serviço pode simplesmente executar a consulta, passar o
conjunto de resultados para o construtor do adaptador, e retornar
a instância do adaptador:
@RPC(method="GET", path="products")
public ResultSetAdapter getProducts() throws SQLException {
Statement statement = getConnection().createStatement();
return new ResultSetAdapter(statement.executeQuery("SELECT * FROM
Products"));
}
5. A resposta produzida pelo método poderia ser algo como este,
onde cada objeto na matriz representa uma linha do conjunto de
resultados:
[
{
"productCode": "S10_1678",
"productName": "1969 Harley Davidson Ultimate Chopper",
"productLine": "Motorcycles",
"productScale": "1:10",
"productVendor": "Min Lin Diecast",
"productDescription": "This replica features working kickstand..."
,
"quantityInStock": 7932,
"buyPrice": 48.81,
"MSRP": 95.7
},
...
]
Com apenas algumas linhas de código, os resultados da consulta
são rápida e eficientemente retornado para o chamador, com o
quadro que garanta que os recursos de banco de dados
subjacentes forem correctamente eliminadas, uma vez a resposta
foi enviada.