CMDBuild Forum

Chiave primaria Relazioni N-M

Salve,

descrivo brevemente il mio scenario in modo da essere il più chiaro possibile nella domanda:

ho due classi:

- Computers

- Computer Components

in relazione N-M tramite un opportuno dominio che ha due attributi: Seriale, Data installazione.

Un componente può essere in relazione a più computer indicando ovviamente seriali diversi.

Il problema è che non posso assegnare un componente più volte con allo stesso computer anche cambiando il seriale (Errore: Can't create the relation).

Guardando il DB sembra che il problema sia dovuto alla struttura della chiave primaria:

PRIMARY KEY("IdDomain", "IdClass1", "IdObj1", "IdClass2", "IdObj2", "BeginDate");

per risolvere ho provato ad aggiungere il campo seriale nella chiave ma il problema persiste.

 

L'intenzion è quella di avere un'anagrafica dei componenti riusabile da assegnare ai computer con seriali diversi.

 

Grazie

Elia

 

 

 

Divido la risposta in due punti.

 

Il primo punto per dire che gli attributi sulle relazioni vanno utilizzati per registrare informazioni specifiche della relazione.

Un esempio è il colore oppure il numero del cavo che collega un server al patch panel.

Il serialnumber del server non è invece un attributo della relazione ma un attributo del server.

 

Il secondo punto per confermare che la chiave primaria delle relazioni è effettivamente errata in quanto non include gli attributi definiti sulla relazione.

Per come è costruita impedisce di avere più collegamenti con attributi diversi fra una stessa coppia di schede, quindi se un server avesse due cavi (su due interfacce di rete diverse) collegati allo stesso patch panel effettivamente otterrebbe un errore.

Come workaround temporaneo può modificare la chiave primaria aggiungendo la colonna "Id", facendo poi attenzione a non inserire righe doppie.

Oppure può aggiungere manualmente nella chiave gli attributi della relazione, facendo poi attenzione ad aggiornarla in caso di aggiunta / rimozione degli attributi.

 

CMDBuild Team

Grazie per la pronta risposta,

ad ogni modo il seriale che intendo io non è del server ma del componente: mettendo l'attributo seriale sulla relazione riesco a riutilizzare l'anagrafica del componente per più server.

Quindi posso associare con seriali diversi la stessa anagrafica componente (es vendor, model, etc) a più computer.

 

Ho già tentato con la modifica della chiave primaria

in questo modo:

ALTER TABLE "Map_computer2computer_component"

  ADD CONSTRAINT "Map_computer2computer_component_pkey" PRIMARY KEY("IdDomain", "IdClass1", "IdObj1", "IdClass2", "IdObj2", "BeginDate","serial");

 

il solo seriale dovrebeb essere sufficiente per garantire l'univocità della relazione nel caso in cui lo stesso componente è associato allo stesso computer ( ad esempio due banchi di RAM identici con seriali diversi)

Il problema è che ottengo sempre lo stesso errore e l'inserimento non va a buon fine. (ovviamente ho impostato l'obblogatorietà dell'inserimeno del campo seriale)

 

Grazie

Elia

Se si tratta del serial del componente il ragionamento è simile, nel senso che avrebbe più senso configurarlo come attributo del componente.

Gli attributi della relazione servono per registrare informazioni tipiche del collegamento, non delle schede collegate.

Se vuole riutilizzare lo stesso componente per più server deve semplimente creare un dominio N:N (considerato che un server potrà avere più componenti), scollegato quindi da attributi reference.

Il fatto che l'errore si ripresenti vuol dire che ci sono due relazioni con dominio, scheda di partenza, scheda di arrivo e seriale identici, il che non avrebbe senso dal punto di vista fisico (lo stesso componente con lo stesso seriale sarebbe collegato due volte allo stesso server).

CMDBuild Team

Mettendo il seriale sulla classe componente di conseguenza sarò obbligato ad avere più record che descrivono lo stesso componente (vendor, modello)  usando poi il seriale per esprimere il fatto che sono installati in  server diversi.

Giusto per spiegarmi in modo migliore, lo scenario da descrivere è questo:

 

Classe Server

-------------------

ID | Nome

1   | Server1

 

Classe Componente

--------------------------

ID | VENDOR | Description

1 | A-DATA | Modulo RAM DDR2

512 MB

 

Map_Server2Componente

----------------------------------

IdClass1|IdObj1|

IdClass2 | Seriale

Server | 1 | Componente | 1 | AAASDJSHSSAD

Server | 1 | Componente | 1 | ZAZAKANNAKNS

 

Il vantaggio di mettere il seriale nella relazione è che posso riutilizzare l'anagrafica del componente quante volte voglio senza creare troppi record inserendo più volte gli stessi dati.

 

Ho fatto come suggerito includendo l'Id nella chiave primaria della tabella di Map far le classi, ho usato

questo script:

ALTER TABLE "Map_computer2computer_component"

  ADD CONSTRAINT "Map_computer2computer_component_pkey" PRIMARY KEY("IdDomain", "IdClass1", "IdObj1", "IdClass2", "IdObj2", "BeginDate","Id");

 

ma quando tento di aggiungere la seconda relazione ottengo l'errore riportato sotto. Mi scuso per la puntualizzazione ma ci tenevo a spiegare meglio il problema. Credo che l'inserimento dell'attributo seriale sulla relazione sia più che opportuno per rappresentare ciò che voglio.

 

Grazie di nuovo per il supporto.

Elia

 

 

org.cmdbuild.exception.ORMException: ORM_ERROR_RELATION_CREATE

    at org.cmdbuild.exception.ORMException$ORMExceptionType.createException(ORMException.java:58)

    at org.cmdbuild.dao.backend.postgresql.PGCMBackend.createRelation(PGCMBackend.java:1143)

    at org.cmdbuild.elements.RelationImpl.create(RelationImpl.java:117)

    at org.cmdbuild.elements.AbstractElementImpl.save(AbstractElementImpl.java:76)

    at org.cmdbuild.elements.RelationImpl.save(RelationImpl.java:104)

    at org.cmdbuild.elements.proxy.RelationForwarder.save(RelationForwarder.java:22)

    at org.cmdbuild.elements.proxy.RelationProxy.save(RelationProxy.java:52)

    at org.cmdbuild.servlets.json.management.ModCard.saveRelation(ModCard.java:785)

    at org.cmdbuild.servlets.json.management.ModCard.createRelations(ModCard.java:749)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

    at java.lang.reflect.Method.invoke(Unknown Source)

    at org.cmdbuild.servlets.JSONDispatcher.dispatch(JSONDispatcher.java:94)

    at org.cmdbuild.servlets.JSONDispatcher.doPost(JSONDispatcher.java:55)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.cmdbuild.filters.AuthFilter.doFilter(AuthFilter.java:54)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.cmdbuild.filters.PatchManagerFilter.doFilter(PatchManagerFilter.java:28)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.cmdbuild.filters.ConfCheckFilter.doFilter(ConfCheckFilter.java:31)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.cmdbuild.filters.TranslationFilter.doFilter(TranslationFilter.java:37)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)

    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)

    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)

    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)

    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)

    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)

    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)

    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)

    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)

    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)

    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

    at java.lang.Thread.run(Unknown Source)

Per quanto riguarda l'errore dovremmo fare delle verifiche, ma è quella la modifica che normalmente apportiamo alla chiave univoca per poter inserire due coppie di schede uguali con attributi sulla relazione diversi.

 

Per quanto riguarda invece i criteri di modellazione del database confermo quando indicato nella risposta precedente, nel caso il vostro obiettivo fosse quello di censire singolarmente ciascun CI, come viene normalmente fatto in un sistema di asset management.

 

Se invece la vostra scheda componente corrispondesse ad un articolo generico allora è corretto il fatto di gestire il serialnumber come attributo della relazione. Consideri però che questa tipologia di modellazione esclude o riduce la possibilità di utilizzo di altri meccanismi (widget, ecc) disponibili nel sistema CMDBuild.

 

CMDBuild Team