La progettazione OO o la progettazione del database dovrebbero guidare la codifica delle mie classi @Entity?

2

Ho due classi che desidero collegare tra loro in un'applicazione JEE usando JPA2. In un mondo OO, direi che una Chatroom ha un attributo Elenco messaggi. Nel mondo relazionale la composizione non esiste in questo modo. Se non stessi coinvolgendo un database, sicuramente codificherei queste due cose come una composizione dei messaggi all'interno della Chatroom. Ma dal momento che sto usando ORM con la specifica JPA2 ho deciso di provare a creare gli oggetti @Entity come scritto di seguito con il fatto che verranno mappati al database in mente.

La mia domanda è: dovrei farlo? È appropriato suddividere le classi @Entity per supportare quello che sembra l'approccio più relazionale? O dovrei semplicemente progettare da una prospettiva OO e cercare di ignorare il fatto che esiste un ORM che lo guida dal basso? In questo momento sto guidando il mio progetto dal lato del database, ma dovrei farlo in un altro modo? Ci sono implicazioni che mi mancano nel farlo in questo modo?

package org.janp.castlerock;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Chatroom {
    private String name;

    @Id
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}



package org.janp.castlerock;

import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
public class Message {
    private int id;
    private Chatroom chatroom;
    private Date timestamp;
    private String text;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    @Temporal(TemporalType.TIMESTAMP)
    public Date getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(Date timestamp) {
        this.timestamp = timestamp;
    }

    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }

    @ManyToOne
    @JoinColumn(name="name")
    public Chatroom getChatroom() {
        return chatroom;
    }
    public void setChatroom(Chatroom chatroom) {
        this.chatroom = chatroom;
    }
}
    
posta Jazzepi 26.04.2012 - 20:06
fonte

4 risposte

2

In teoria, nessuno di questi approcci è veramente "OO", dal momento che stai esponendo tutto lo stato interno all'esterno (non c'è incapsulamento). Quindi, da questa prospettiva, la tua domanda diventa davvero: dovrei aggiungere gli attributi di raccolta / getter / setter al mio DAO (Data Access Objects). Poiché ciò esporrà ulteriormente lo stato interno, sono tentato di rispondere con "no".

Inoltre, poiché stai facendo ipotesi sull'uso previsto dei tuoi oggetti (chiedendo che l'elenco recuperi tutti i messaggi, senza alcuna selezione), potresti davvero incoraggiare i programmatori a bypassare le strategie di ottimizzazione che un database potrebbe darti. Per chiarire questo con l'esempio; potresti bypassare un indice efficiente recuperando tutti gli oggetti e ordinandoli o selezionandoli successivamente.

Dal punto di vista pratico, l'aggiunta di questi accessori di accesso alle liste è spesso utile. Consente un modo più naturale di navigare nel grafico degli oggetti e spesso è più efficiente per i piccoli set, dal momento che hai un maggiore controllo sulla memorizzazione nella cache.

Vorrei concludere dando un consiglio sonoro. Crea una chiara definizione tra i tuoi DAO e i tuoi modelli. Cerca di non lavorare direttamente su DAO da una GUI e considera l'aggiunta di un livello di business logic in mezzo. All'inizio potrebbe essere leggermente più difficile, ma ridurrà la complessità e promuoverà la riusabilità. Forse, quando il tuo livello logico aziendale è completo, scoprirai che non hai bisogno di molti di quei fastidiosi DAO, dopotutto. Potresti trovare soluzioni di archiviazione dei dati che funzionano in modo più efficiente aggirando il sovraccarico delle chiamate DB.

    
risposta data 26.04.2012 - 22:11
fonte
1

Scrivi i tuoi oggetti come oggetti. Lascia che il mappatore gestisca il lato relazionale delle cose. Preferirei che una chattenda dica:

Collection messages=chatroom.getMessages();

invece di dover eseguire una nuova query di Messaggi in cui ChatroomId == chatroom.getId () in particolare vedendo che Java non ha un LINQ equivalente

    
risposta data 26.04.2012 - 21:17
fonte
0

Attualmente sto lavorando con un ORM (Doctrine 2 in PHP) e lavoro in questo modo:

Ad esempio, ho dovuto creare un componente di gestione della libreria multimediale con le seguenti entità associate:

  • Media (contiene la descrizione e il percorso del supporto reale)
  • MediaType (video, immagine o audio)
  • MediaExtension [per tipo] (.mp4, .jpg, .mp3, ecc.)

Queste entità sono utilizzate per definire la struttura del mio DB e la relazione tra oggetto (un'entità potrebbe gestire anche una tabella di giunzione, quindi non mappano 1 a 1 con il mio database)

Queste tre entità dove poi sono state iniettate nel modello che conteneva tutta la logica e dal momento che tutte queste entità erano in relazione l'una con l'altra per gestire la libreria, tutto il codice richiesto contenuto è la mia classe del modello.

Quindi nel tuo caso, potresti creare un modello che gestisca la chat con le seguenti entità:

  • Stanza (definire la chat room effettiva (regole, amministratori, argomento, nome, ecc.)
  • Messaggio (messaggi scambiati tra utenti)
  • Utenti (gestirà solo la parte in cui un utente crea un nuovo messaggio e forse alcune opzioni come il nome visualizzato. Questa entità sarebbe anche presente nel tuo modello utente che gestisce la creazione dell'utente e la modifica approfondita)

Questo sarebbe più vicino a un Domain Driven Design (la gestione dei dati è mappata per adattarsi ai requisiti dell'applicazione, dà un tocco più user-friendly all'applicazione) al contrario di un Data Driven Design (dove la struttura del database guida come il requisito dell'applicazione sono impiantati)

    
risposta data 26.04.2012 - 20:55
fonte
0

Solo i miei due centesimi qui. Da quando ho iniziato a lavorare con asp.net mvc insieme al framework di entità, che anche se è davvero facile procurarmi una rappresentazione di database di un tavolo, potrebbe non essere quello che mi serve.

Ho scoperto che la creazione di ciò che alcuni chiamano un ViewModel, una classe che ha tutto il necessario per rappresentare l'oggetto reale con cui si lavorerà, è stata davvero una buona idea. Mentre sembra che tu stia creando un lavoro extra, con un modello di base che assomiglia a una tabella e un secondo modello che ricrea appena tali proprietà (e / o aggiunge di più in base alla situazione), penso che la flessibilità sia un compromesso migliore .

Quindi sono d'accordo con gli altri qui e dico, scrivi i tuoi "viewModels" per abbinare ciò di cui hai veramente bisogno, e mappali semplicemente su un modello di 'entità' quando hai bisogno di salvarli o accedervi dal database.

Spero che questo aiuti alcuni, e buona fortuna per il tuo progetto.

    
risposta data 26.04.2012 - 21:45
fonte

Leggi altre domande sui tag