Como criar relacionamentos complexos
21/02/2015 09:52
0
Ola pessoal, estou iniciando no Grails, e não encontro documentação que fala desta situação.

Seguinte gostaria de saber como fazer um relacionamento muito para muitos na seguinte situação o sistema tem varias entidades, e todas elas se relacionam a uma entidade que pode existir ou não, mas se existir obrigatoriamente ela tem que ter um relacionamento com pelo menos uma entidade de origem ou varias. Bem não sei se consegui me explicar bem, então abaixo fiz na medida do possível uma representação das entidades. Não faço ideia de como faria em Grails ao que chegue neste resultado.

Desde já obrigado.


________________________
|Origem 1
_______________________|
|pK_o1|Desc 1 |
_______________________
|1 |Aaaaaaaaaaaaaaa |
_______________________
|2 |Bbbbbbbbbbbb |
________________________

________________________
|Origem 2
_______________________|
|pK_o1|Desc 2 |
_______________________
|1 |ccccccccccccc |
_______________________
|2 |Dddddddddddd |
________________________

________________________
|Origem N
_______________________|
|pK_o1|Desc N |
_______________________
|1 |Eeeeeeeeeeee |
_______________________
|2 |Ffffffffffff |
________________________

________________________
|Obj Relacionado
_______________________|
|pK_o1|Desc N |
_______________________
|1 |Ggggggggg |
_______________________
|2 |Hhhhhhhhhhhh |
________________________
|3 |Iiiiiiiiiiih |
________________________


___________________________________
|Relacionamento
___________________________________|
|ID_OBJ_REL| ID_OBJ_ORI | TIPO_ORI |
___________________________________
|1 |1 |Origem 1 |
___________________________________
|2 |1 |Origem 2 |
___________________________________
|3 |2 |Origem 1 |
___________________________________
|3 |2 |Origem N |
___________________________________

Tags: hasMany, muitos para muitos


0
Ola, Rogerio. Se entendi bem o que você ta tentando fazer, acredito que uma possivel solução seja essa:

abstract class Origem {
static hasMany = [relacionados: Relacionado]
}

class Origem1 extends Origem {
String aaaaa
String bbbbb
}

//Idem para Origem2, Origem3, ..., OrigemN

Class Relacionado {
static hasMany = [origens: Origem]

static constraints = {
origens minSize: 1
}
}


Não cheguei a testar. Pode ter algum problema, mas acredito que funcione.

Se não era bem isso que você queria fazer, você pode dar mais detalhes?
Talvez uma representação UML...
Abraço
21/02/2015 12:05


0
Oi Yago,

Valeu, a sua resposta me ajudou bastante, ainda não sei se ficou exatamente do jeito que eu queria, mas acho que sim, acho que uma questão agora de acerta a View,mas como não me aprofundei nos estudos das tags ainda não saberia como acerta. e o Banco eu não sei como ficou porque ainda estou usando o temporário, agora que vou ver como por para o postgre. em todo caso segue como fiz a minhas classes de exemplo a as observações.

1) A classe BaseEntity não ficou abstract por que na hora de executar o generate-all, ela dava um porque em alguma parte criava um new BaseEntity o que não e possível de ser feito.

2)O resultado da View para incluir foi o que eu esperava, consegui cadastrar os dados relativos a origem, e no incidente ao cadastrar me lista todas elas certas, mas o problema e na hora de consultar porque o link aponta para uma view relativa ao BaseEntity e não a classe filha certa, mas acredito que é só estudar mais para acertar a view.

3) Como ficaram as classes



class BaseEntity{
String name
static belongsTo = Incident
static hasMany = [incidents:Incident]
static constraints = {

}
static mapping = {
id generator: 'identity'
incidents joinTable: [name: "mm_incident_entity", key: 'mm_orige_id' ]
}
String toString(){
return this.name
}
}


class Classe1 extends BaseEntity{
String description
static belongsTo = Incident
static hasMany = [incidents:Incident]
static constraints = {
description size: 5..500
}

String toString(){
return this.name
}
}

class Classe2 extends BaseEntity{
String kind
static belongsTo = Incident
static hasMany = [incidents:Incident]
static constraints = {
kind inList:["val1", "val2", "val3"]
}

String toString(){
return this.name
}
}


class Incident {

String title

static hasMany = [origens:BaseEntity]

static constraints = {
origens minSize: 1
}
static mapping = {
id generator: 'identity'
origes:joinTable: [name: "mm_incident_entity", key: 'mm_incident_id' ]
}
String toString(){
return this.title
}
}



0
Bom, vamos por partes:
o Banco eu não sei como ficou porque ainda estou usando o temporário

O banco deve estar um pouco diferente do que você citou na pergunta.
Ele deve ter uma única tabela para toda a hierarquia de Baseentity. Esse é o padrão do grails.
Essa estrategia normalmente é mais barata, mas se você fizer questão por algum motivo de ter uma tabela para cada subclasse insere a seguinte linha em mappings na classe BaseEntity:

tablePerHierarchy false



1) A classe BaseEntity não ficou abstract por que na hora de executar o generate-all, ela dava um porque em alguma parte criava um new BaseEntity o que não e possível de ser feito.

Bom, acredito que o scaffold não deva funcionar mesmo com classes abstratas. Mas você pode gerar um controller para cada subclasse BaseEntity ou implementar seu proprio BaseEntityController.

2)O resultado da View para incluir foi o que eu esperava, consegui cadastrar os dados relativos a origem, e no incidente ao cadastrar me lista todas elas certas, mas o problema e na hora de consultar porque o link aponta para uma view relativa ao BaseEntity e não a classe filha certa, mas acredito que é só estudar mais para acertar a view.

Não entendi muito bem o que você quis dizer aqui. Você pode dar um exemplo? Como você ta gerando esse link que ta apontando pro lugar errado? Você ta usando scaffold?
recomendo que você talvez use o scaffold só para gerar a base das suas views e controllers para depois customiza-los.

3) Como ficaram as classes
<classes>

Cara, acho que você não precisa colocar
static hasMany = [incidents:Incident]
em Classe1 e Classe2 uma vez que ambas herdam o relacionamento de BaseEntity. Não sei nem qual vai ser o comportamento do grails nesse caso.

24/02/2015 15:06


0
Oi Obrigado pela a ajuda, vc tinha razão, ele criou tudo em uma tabela só, agora ele criou tudo separado, ainda estou avaliando se gostei kk.

Abaixo vou fazer as considerações com relação as perguntas.

1)Confesso que não entendi bem o que vc falou sobre o abstract, porque na verdade de forma ideal,ela realmente deveria ser abstrata e nem ter controller e view, tanto que nem criei, mas ao executar o generate-all ele criou tudo. Mas a parte de como customizar as views eu ainda vou estudar. no momento to focado no back-end, quando chegar no front-end, vou abrir muitos tópicos por aqui kk.

2)Na view show.gps do incidente ele criou um link conforme abaixo, para os objetos associados a incident.


<g:link controller="BaseEntity" action="show" id="${o.id}">${o?.encodeAsHTML()}</g:link>


Resolvi com o seguinte código

<g:if test="${o.instanceOf(classe1)}">
<g:link controller="classe1" action="show" id="${o.id}">${o?.encodeAsHTML()}</g:link>
</g:if>
<g:elseif test="${o.instanceOf(classe2)}">
<g:link controller="classe2" action="show" id="${o.id}">${o?.encodeAsHTML()}</g:link>
</g:elseif>


3)Vc tem razão, e foi uma distração minha,que ao editar o arquivo de exemplo esqueci de tirar a linha. E o comportamento, parece que o grails simplismente ignorou porque com e sem a linha o resultado foi o mesmo.

Mais uma vez obrigado



Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto