O que você pensaria sobre uma nova ferramenta de persistência Java, que não é realmente um ORM? [fechadas]

12

Persistência em Java

Nos últimos anos, acumulei experiência no campo da abstração de persistência em Java, usando conceitos como EJB 2.0, Hibernate, JPA e outros desenvolvidos em casa. Eles me pareciam ter uma curva de aprendizado acentuada e muita complexidade. Além disso, como grande fã do SQL, também pensei que muitos modelos de abstração fornecem muita abstração sobre o SQL, criando conceitos como "critérios", "predicados", "restrições" que são conceitos muito bons, mas não o SQL.

A idéia geral de abstração de persistência em Java parece basear-se no modelo Objeto-relacional, em que o RDBMS é de alguma forma compatível com o mundo OO. O debate sobre ORM sempre foi emocional, pois parece não existir uma solução única que seja adequada a todos - se é que essa solução pode existir.

jOOQ

Minha preferência pessoal de como evitar problemas relacionados ao ORM é manter o mundo relacional. Agora, a escolha do paradigma do modelo de dados não deve ser o tópico de discussão, pois é uma preferência pessoal ou uma questão de qual modelo de dados melhor se adapte a um problema concreto. A discussão que eu gostaria de iniciar é sobre a minha própria ferramenta de persistência chamada jOOQ . Eu projetei o jOOQ para fornecer a maioria das vantagens das modernas ferramentas de persistência:

  • Uma linguagem específica de domínio baseada em SQL
  • Geração de código-fonte mapeando o esquema do banco de dados subjacente para Java
  • Suporte para muitos RDBMS

Adicionando alguns recursos que poucas ferramentas modernas de persistência possuem (me corrija se estiver errado):

  • Suporte para SQL complexo - uniões, seleções aninhadas, junções automáticas, alias, cláusulas de caso, expressões aritméticas
  • Suporte para SQL não padrão - procedimentos armazenados, UDT, ENUMS, funções nativas, funções analíticas

Por favor, considere a página da documentação para obter mais detalhes: http://www.jooq.org/learn.php . Você verá que uma abordagem muito semelhante é implementada no Linq para C #, embora o Linq não tenha sido projetado exclusivamente para SQL.

A questão

Agora, tendo dito que sou um grande fã de SQL, me pergunto se outros desenvolvedores compartilharão meu entusiasmo pelo jOOQ (ou Linq). Esse tipo de abordagem para abstração de persistência é viável? Quais são as vantagens / desvantagens que você pode ver? Como eu poderia melhorar o jOOQ e o que está faltando na sua opinião? Onde eu errei, conceitualmente ou praticamente?

Respostas críticas, mas construtivas, apreciadas

Entendo que o debate é emocional. Existem muitas ferramentas excelentes por aí que já fazem coisas semelhantes. O que me interessa é um feedback crítico, mas construtivo, com base em sua própria experiência ou artigos que você possa ter lido.

Lukas Eder
fonte
Ele lida com transações?
Armand
@ Alison: Não, é apenas sobre SQL. Manipulação de transações é um negócio muito complexo que eu acho que muitas outras ferramentas / frameworks (incluindo EJB2 / 3) irá lidar melhor do que jOOQ
Lukas Eder
Eu sugeriria fortemente um caso de uso muito sólido e detalhado, onde você mostra que sua abordagem é excelente para resolvê-la.
Observe também que editar ESTE pesado tornará as respostas mais ou menos irrelevantes e, portanto, inutilizáveis ​​para futuros leitores. Faça uma pergunta nova e melhor.
Oi Thorbjorn. Você quer dizer um caso de uso diferente dos mostrados na página de exemplos? Ou você gostaria de ver alguns exemplos na própria pergunta? Sobre a edição: você está certo em geral. Neste caso, no entanto, eu pensei que as duas respostas que eu tenho até agora teria sido um pouco o mesmo ...
Lukas Eder

Respostas:

5

Acho que você está no caminho certo e deve continuar com sua solução. Algumas das críticas anteriores são excessivamente duras, mas alguns argumentos válidos são feitos.

Eu também procurei muito e em busca de uma solução ORM com todos os recursos que atendesse às minhas necessidades, mas todas as soluções que eu observei foram insuficientes. Cada um tem seus prós e contras, mas nenhum realmente fez tudo o que eu queria. Concordo com a sua crítica a essas soluções - ou seja, elas geralmente são complexas e têm uma curva de aprendizado acentuada.

O principal concorrente teria que ser o padrão de fato, o Hibernate. É completo, robusto e bem testado. Eu respeito e aprecio o que é. Agora, correndo o risco de ofender metade da comunidade de programação, também devo dizer que é uma parte inchada e complexa de código de não desempenho. Passei bastante tempo vasculhando suas entranhas, tentando depurar e entendê-lo, e não fiquei impressionado com o que vi. Dito isto, eu ainda o recomendaria como ponto de partida para quem procura um bom ORM. Ele é excelente em CRUD simples, mas eu não o usaria para consultas em massa de alto desempenho, como mineração de dados ou processamento de números.

Infelizmente, meu aplicativo é mais da variedade de trituração de números (embora também exista algum CRUD), então decidi fazer o meu próprio. Eu sabia desde o início que seria insignificante em comparação com as outras soluções existentes, mas seria bom o suficiente e me proporcionaria o desempenho necessário. Agora, aqui está a parte realmente boa: parece muito com a sua solução!

Isto é o que eu acho que você fez mais certo: você declarou suas crenças subjacentes como um tipo de declaração de missão, e essas crenças estão corretas. Obviamente, passei bastante tempo pensando sobre esse problema e é difícil de resolver. Mas com o passar do tempo, acho que a comunidade de programação entende melhor e criaremos melhores soluções. Parabéns a todos os esforços anteriores (especialmente o Hibernate), mas acho que podemos fazer melhor.

Sua solução refina melhor o problema, mas apenas resolve parte dele. Eu acho que uma abordagem em camadas pode nos dar tudo o que queremos. O que você criou / IMO é a camada de base. Como você sugeriu, acho que essa camada é melhor gerada automaticamente com base em um esquema de banco de dados. Deve ser um modelo de objeto relacional muito simples que mapeia diretamente no banco de dados e não mais. Você está certo de que os dados persistem por muito mais tempo que o código; portanto, nesse nível, os dados devem gerar código e não vice-versa. Seria compatível com CRUD e com consultas em massa de alto desempenho. Eu provavelmente implementaria algum tipo de cache L1 nessa camada.

No entanto, o que outras soluções ORM destacam é a capacidade de definir seus objetos de uma maneira que não dependa muito da estrutura real do banco de dados subjacente. Para essa funcionalidade, eu criaria outra camada. Por necessidade, essa camada se torna mais abstrata, esperançosamente mais simples (às custas da funcionalidade perdida) e se baseia na camada anterior. Pode utilizar um cache L2.

Estou aberto a ter mais camadas, mas o ponto principal para mim é que, ao fornecer vários pontos de entrada na biblioteca, você pode atender a todas as necessidades. Para aqueles que desejam uma solução simples de CRUD que mapeie diretamente os objetos de sua escolha, eles podem criar na camada superior. Para aqueles que procuram algo mais poderoso e com melhor desempenho, mas que desejam incorrer na complexidade adicional, eles podem se conectar à camada inferior. Eu não criaria uma linguagem de consulta especial, mas exporia o objeto do construtor de consultas para essa finalidade. E como o código é estratificado, essa funcionalidade existe naturalmente sem passagem especial.

Acho que você tem uma compreensão do espaço e não está reinventando a roda, mas atingiu um nicho um pouco diferente. E, francamente, esta é uma roda que poderia usar melhorias de qualquer maneira. Você enfrenta uma batalha difícil lutando contra as potências do passado, mas se sua solução for boa, e eu acho que está indo nessa direção, ganhará popularidade por seus próprios méritos.

Dale Anderson
fonte
Oi Dale, obrigado por seu incentivo! Eu gosto do seu fraseado sobre as camadas e o jOOQ estar na camada mais baixa, com mais abstração possível em cima do jOOQ. É algo que quero abordar quando tiver impulso suficiente com o jOOQ. A interface com o JPA e / ou o Hibernate estará claramente no roteiro. Como você diz, essas ferramentas se destacam na simplicidade por meio da abstração e têm muitos recursos que eu não quero na minha camada: transações, sessões, caches L2, etc. PS: Sua solução é de domínio público? Eu estaria muito interessado!
Lukas Eder
8

"Existem muitas balas mágicas por aí, e não faltam desenvolvedores ingênuos."

Sem ofensas, parece que você não entende completamente o que já foi feito neste espaço e, portanto, está reinventando algumas rodas - a experiência nos diria tudo o que as rodas que você inventa, embora limpas e divertidas, provavelmente não são tão bom ou útil como as rodas bem refinadas já disponíveis.

quentin-starin
fonte
1
Obrigado pelo seu feedback! Você deu uma olhada mais profunda na minha biblioteca? Eu exatamente tento "abandonar o" como o seu artigo chama. O jOOQ quer que os desenvolvedores escrevam SQL, não código mapeado em OR. Tento alcançar o que o Linq faz pelo .NET sem poder reescrever o compilador Java. Parabéns à Microsoft pelo Linq! E ouso dizer que não sou ingênuo, porque criei o jOOQ depois de não estar satisfeito com o EJB 2.0 (há algum tempo), nem com o Hibernate. Precisamente pelas razões apontadas em seu artigo. Eu tentei o que foi feito e não atendeu às minhas necessidades.
Lukas Eder
O jOOQ deseja que os desenvolvedores usem sua API do tipo Critério. Isso não é SQL. É uma maneira de criar SQL que, na realidade, é mais feio e mais complicado que o SQL, com muito pouco ou nenhum benefício real. "q.addCompareCondition (TAuthor.YEAR_OF_BIRTH, 1920, Comparator.GREATER);" Não vejo nada realmente diferente de qualquer outra ferramenta de geração de classe por tabela. O que significa, como eu disse, há uma probabilidade quase certa de que uma melhor já exista. Os campos de sequência de caracteres gerados por modelo nem se aproximam do que as expressões lambda permitem.
usar o seguinte
1
É um pouco difícil para mim entender a motivação por trás da sua resposta / comentário. Ainda acho que você não teve uma análise completa dos exemplos que forneci (você citou o primeiro exemplo) e sua comparação com produtos concorrentes me parece um tanto vaga. O objetivo da minha pergunta era obter feedback construtivo, e eu apreciaria exatamente isso. Você menciona "ferramentas melhores" e "expressões lambda". Você poderia por favor elaborar? Como o jOOQ se compara às ferramentas que você mencionou? Como as expressões lambda são implementadas no Java 6 - antes que a Oracle possa adicioná-las no Java 8? Mais uma vez obrigado
Lukas Eder
2

Um cenário que tornaria esse tipo de API adequado é quando você precisa de um construtor SQL independente do banco de dados que a maioria do ORM não permite. Uma grande situação em que precisei está na geração de relatórios. Eu precisava criar o SQL de maneira orientada a objetos e executar esse sql em vários bancos de dados para teste. O Hibernate e outro ORM são muito dependentes das configurações, limitando assim minha construção do sql, de modo que não posso combinar a tabela onde a associação não existe nos xmls. Como qualquer associação é possível no Módulo de relatório que estou desenvolvendo, procurei algo diferente. Então me deparei com a JOOQ. Apenas resolve meu problema. Eu só precisava de um acesso somente leitura, nunca encontrei problemas de depuração dolorosos como no hibernate.

Na verdade, estou planejando desenvolver uma maneira diferente de modelar dados em vez da maneira comum do POJO e usar o JOOQ como um dos alicerces, que é uma camada para construir o SQL. Portanto, além do JOOQ, estou planejando criar uma maneira mais flexível de modelar dados / entidades usando HashMaps. Meu design tornaria possível integrar o design de front-end e back-end mais facilmente em um ponto de entrada, embora eu usasse várias camadas para concluir a estrutura, exatamente como o que os comentários acima disseram. O JOOQ realmente desempenhará um papel muito bom, como no meu próprio projeto, ele serve como uma das fundações ou pilares.

Então continue com o bom trabalho lukas!

videira
fonte
1

Se eu entendo sua ferramenta corretamente, ele mapeia objetos diretamente para uma estrutura conceitual de SQL, em vez de mapear objetos que implementam algum mapeamento para a funcionalidade SQL (ORM), quase como uma abstração ORM-- para maior controle nerd, para que você possa usar mais recursos SQL ORMs geralmente não dariam a você?

Não tenho certeza de qual problema você está tentando resolver. Como sua ferramenta requer um conhecimento profundo de SQL, as pessoas não usariam apenas, bem, SQL? É o código de cola que você está tentando se livrar? Melhor validação das consultas SQL por meio de modelagem de API em vez de cadeias simples?

Devo admitir que seus exemplos JOOQ se parecem com versões LISP do SQL. Não que isso seja uma coisa ruim :) e eu vejo algumas coisas avançadas interessantes, mas as vantagens que você lista desaparecem lentamente à medida que se tornam cada vez mais avançadas (mais configurações, menos abstratas, mais arraigadas no santuário interno do SQL específico motor, etc.)

Uma sugestão que eu gostaria de ver que sinto falta na maioria dos ORMs é uma estrutura que pode lidar com objetos de maneira não relacional, traduzindo interações de objetos em qualquer que seja o back-end (SQL, NoSQL, mapas de tópicos, RDF etc.) .), que requer armazenamento em cache do modelo usado, em vez de especificidades de interações, dialetos e pensamento relacional do SQL.

IMHO, é claro. :)

AlexanderJohannesen
fonte
Olá, obrigado pelo seu feedback. Você acertou. Como o qstarin colocou, tento remover o "O" do ORM e permanecer relacional. Por que não SQL simples? Você quer dizer JDBC? Você já consultou seu banco de dados com 5 seleções aninhadas e várias junções, funções analíticas com JDBC? Erros de sintaxe, incompatibilidade de ligação, etc. Infelizmente, o jOOQ não pode ser a ferramenta certa para você, porque não há possibilidade de mapear QUALQUER modelo para objetos. E eu não quero isso. jOOQ DEVE ser relacional. Para os desenvolvedores que preferem esse modo de pensar. Para o outro, eu recomendo o JPA .. Ou o Linq, se você estiver executando o .NET.
Lukas Eder