Eu estou estudando hibernate para um projeto e dentro de uma das documentações eu li isto:
There is an alternative <composite-id> declaration to allow access to legacy data with composite keys. We strongly discourage its use for anything else.
“Legacy data”?! Pq isso? Desde quando chave primaria composta é desencorajada e pq?
Problema de comandos em cascata…
Vc teria que utilizar alguma forma de versionamento para saber se uma classe foi modificada, ou não.
Dá uma olhada no capítulo 16 da documentação de referência do hibernate.
Segundo, que nem sempre vc vai querer ter o objeto instanciado e persistido, só porque vc tem as informações que compõe ele.
É muito complexo utlizar chaves compostas ! Para começar vc precisará utilizar uma classe a mais…
Qual é o benefício !?
Porque não utlizar uuid, hi-low, ou qualquer outra coisa melhor !?
Sinceramente eu não entendi os dois primeiros motivos. Mas quanto ao terceiro discordo radicalmente. A utilização de chaves compostas aumenta o desempenho em buscas devido a indexação das PK. Obvio que poderiamos criar estes indices, mas mesmo assim retiratiamos do banco de dados a verificação de integridade das PKs. Uma PK gerada automática deve ser utilizada com extrema cautela o seu uso pois estamos retirando do banco de dados uma de suas principais funçoes, que é a unicidade da informação. Deixariamos isto para a camada da aplicação, o que na minha opnião fere alguns dos principios basicos da computação que são as maquinas virtuais e abstração. Eu sei que essa é uma discussão que tem pano pra manga, mas meu principal objetivo é utilizar uma modelagem do banco de dados da maneira tradicional com o hibernate, tem como?
Seguinte, vc tem como utilizar chaves compostas com o Hibernate, mas assim como falou nosso amigo Rodrigo (e aí xará) eu não recomendo…
A primeira observação que ele colocou é o seguinte, se vc utilizar chaves únicas, é possível fazer com que o Hibernate gere as chaves automaticamente para vc. Além disso, o Hibernate terá como saber se o objeto que vc está passando já existe no bd ou não (depende da sua estratégia de unsaved-value, geralmente se a chave for nula ele não está salvo e se tiver valor está). No caso de chaves compostas o Hibernate não poderá gerar as chaves para vc, então vc terá que utilizar uma estratégia de versionamento ou timestamp (a que preferir), ou ainda um esquema com interceptor para poder informar ao Hibernate se ele deve fazer um insert ou um update do objeto.
Além disso, lembre-se que está se tornando cada vez mais comum o uso de chaves únicas (as chamadas surrogate keys) que não possuem vínculo com o negócio!
Se vc procurar pela web papers sobre mapeamento objeto-relacional verá que a maior parte das abordagens são feitas dessa maneira.
Surrogate Keys é um conceito derivado de Data Warehouse, e eu não sei se ele pode ser aplicado em ambiente de produção sem perda de qualidade na verificação de integridade. Alias, essa é a minha grande dúvida. Quem puder me esclarecer, por favor!
Bye
Que tipo de problema vc acha q teria?
Não consigo imaginar algum problema que seria causado pelo uso de Surrogate keys, pelo contrário, vejo mais benefícios do que problemas…
Dando uma olhada no google, verifiquei alguns prós e contras:
Prós:
Não há dados redundantes nas chaves estrangeiras.
Chaves primárias pequenas
Consequentemente, chaves estrangeiras pequenas
Joins rápidos
A chave primária não precisará ser alterada se alguma tabela ter que sofrer alterações na chave unica
Contras:
Não é algo padrão na modelagem relacional
As vezes vão ser necessários um número maior de joins
Terá que criar chaves únicas para manter a integridade
Só para acrescentar um pouquinho ao assunto, eu nunca tinha ouvido esse termo bonito, “Surrogate Keys”, mas em todos os projetos aqui da empresa - mesmo antes dela existir - sempre foi usado esse conceito. Não consigo me imaginar colocando uma string como chave primária de uma tablela.
Minha conclusão:
O uso de Surrogate Keys acarreta numa maior responsabilidade em cima do DBA em criar indices únicos nos campos que deveriam ser chave primária, para manter a unicidade dos dados dentro do banco de dados. Alem de criar indexação nestes mesmo campos para facilitar os Joins. Discordo totalmente que surrogate keys podem tornar as consultas mais rapidas, muito pelo contrário, elas só podem tornar as consultas mais devagares se os índices não forem criados corretamente.
Em compensação, surrogate keys dimininui o impacto no banco de dados ao se alterar as chaves primárias das tabelas, pois com surrogate keys, a chave primária jamais vai ser alterada.
Alguem falou que não imagina o uso de Strings como chave primaria. Discordo tb. Não torna a consulta em nenhum momento mais devagar, o grande problema que pode ocorrer é o fato de vc ter Strings parecidissimas, que deveriam representar um mesmo dado, porém ocorreu a duplicidade devido a algum erro de digitação. Mas sinceramente, colocar o nome de alguem como chave primária é estupidez mesmo… porem, existem estratégias para o uso de Strings como chave primária.
Qualquer abordagem fica uma merda se qualquer coisa não for criada corretamente hehe
[/quote]
Concordo!
Considerar a não criação dos índices não me parece um porquê válido para invalidar o uso de surrogates.
Mas tbm concordo que a consulta pode ficar mais lenta quando vc depender de dados que poderiam estar na pk, mas não estão… Isso acaba obrigando um join extra…
Apesar disso, não acho que esse argumento seja forte o suficiente para invalidar o uso da surrogate.
Mas tbm acho que essa discussão dá muito pano pra manga, se vc olhar em diversos fóruns voltados para design de bd e etc, verá que isso é uma discussão quase infinita, as duas abordagens possuem prós e contras, a escolha deve depender do projeto…
A questão é: vc tem capacidade criar corretamente? Existem diversos programadores que carregam a função de projetar o banco de dados, e aposto que muitos deles não tem conhecimento sobre a necessidade de criar a indexação e campos únicos quando se usa Surrogate.
Strings podem ser consideradas números. Alias, Strings são conjuntos de números binarios que podem (não necessariamente) serem transformadas em um conjunto de caracteres segundo uma tabela de caracteres, como por exemplo ASCII.
No modelo relacional tradicional não existem dados redundantes na chave estrangeira. Se existir é pq foi modelado errado.
Concordo
Pelo contrário, JOINS mais lentos por não estar utilizando a indexação automática das PKs, vc tem que criar o indice vc mesmo, não que isto seja mto trabalho…
Com toda a certeza esse é o maior benefício
E tenho mais um para acrescentar:
Não é capaz de manter a integridade referencial dos dados.
Ex.
User tem N produtos e N grupos de produtos. Produtos podem pertencer a N grupos e grupos podem possuir N produtos.
Surrogate Keys não conseguem manter a integridade desses dados e permitem qualquer um inserir um produto de um User em um grupo de outro User.
Concordo inteiramente com vc. E acho uma pena o Hibernate ser tão radical com o uso tradicional de modelagem ER.
Bye
Vou fazer um balanço da discussão:surrogate_key versus abordagem tradicional
Disvantagens da Abordagem Tradicional
Problema de comandos em cascata…
Rodrigo você foi super didático… Show de bola sua explicação. De forma geral, o problema é :
[quote]
o Hibernate “não” terá como saber se o objeto que vc está passando já existe no bd ou não.
[/quote] Outro subterfúgio terá que ser usado.
O Programador não terá como saber se o objeto já existe no bd ou não? Outro subterfúgio terá que ser usado.
Terá que utilizar uma classe a mais para PK, lembrando de implementar um bom método equals, hashcode e toString para ele.
Chaves compostas são chaves naturais (ou inteligentes, isto é, tem um significado de negócio)
[quote]
The biggest disadvantage for intelligent keys, and a corresponding advantage for surrogate keys, is that primary keys are hard to change
[/quote] Breck Carter
Tabelas maiores , redundância de informação, chaves maiores.
Uma solução é o uso de constraints, que apresenta óbvias desvantagens as chaves compostas. De qualquer forma o banco de dados não pode ser o único responsável pela integridade das informações. É uma sobrecarga desnecessária e errada. A filosofia de programação em camadas (n-tiers), diz que o banco não deveria ser acessado diretamente por outras aplicações. Várias aplicações alterando uma mesma tabela, é muito mais suscetível a violação de consistência do que uma única aplicação.
http://www.corba.ch/e/3tier.html
Mais resposabilidade para o dba: Implicação da criação de índices únicos e constraints
Não é algo padrão na modelagem relacional
Às vezes vão ser necessários um número maior de joins
Conclusão:
Não… O hibernate não é radical. Se você quiser que o hibernate grave informações em cascata, ou que ele decida se deve fazer insert ou update, seria melhor que utiliza-se surrogate keys. Se não quiser, você pode fazer isto na mão ou criar um sistema de versionamento.
Você pode continuar programando da maneira que tradicional, ou avaliar se vale a pena ou não partir para uma abordagem mais voltada orientada a objetos.
Surrogate Keys geram joins muito mais rápidos no caso de voce querer junção natural entre 2 tabelas:
A razão é simples, o tamanho dos índices (FK1, FK2) vai ser muito maior que os (PK1), logo exigindo mais IO do SGDB.
O uso de Surrogate Keys é feito quando se normaliza o banco. Bancos bem normalizados são uma maravilha de dar manutenção e entender.
Quando se usa chaves compostas é exatamente o contrario.
[/quote]