4.1 Transazioni e integrità del database

La normale modalità di funzionamento di un database è quando riceve migliaia di richieste ogni minuto da centinaia di client diversi. In questo caso, si verificano spesso situazioni in cui si accede agli stessi dati da query diverse.

Meno spesso, ma, di nuovo, di tanto in tanto ci sono situazioni in cui una richiesta legge una determinata riga e un'altra richiesta la modifica contemporaneamente. Immagina cosa succede se qualcuno legge una riga che è cambiata solo a metà? Niente di buono.

Questo problema è risolto in diversi modi. Innanzitutto, puoi semplicemente bloccare la linea che cambia. Sia per la lettura che per la scrittura. Questo metodo funziona, ma la velocità della base ne risente notevolmente.

Il secondo modo è bloccare la stringa solo per la scrittura. Tuttavia, ci sarà ancora un problema quando qualcuno tenta di leggere la riga parzialmente modificata. Conclusione: non dovrebbe esserci una situazione in cui la linea è parzialmente modificata.

Pertanto, hanno escogitato un terzo metodo: le transazioni. Una transazione è un gruppo di azioni che vengono eseguite tutte insieme o nessuna. Non può esserci una situazione in cui parte delle azioni è stata eseguita e la seconda parte no. Se non è possibile apportare tutte le modifiche, viene eseguito il rollback di tutte le modifiche già apportate.

Qualsiasi server SQL moderno ti consente di modificare i dati solo nelle transazioni. Si apre una transazione, si apportano modifiche a un numero qualsiasi di tabelle e si esegue il commit della transazione. SQL Server tenta quindi di apportare modifiche. Se tutto va bene, verranno aggiunti al database generale. In caso di problemi, tutte le modifiche verranno annullate.

Anche Hibernate utilizza questo paradigma. Questo è il motivo per cui nella lezione precedente abbiamo visto che durante il tentativo di salvare l'oggetto Employee nel database, è stata prima aperta una transazione e, dopo il salvataggio, ne è stato eseguito il commit.

Approfondiremo questo argomento in modo più dettagliato, ma per ora basta sapere perché sono necessarie le transazioni e dove vengono solitamente utilizzate.

4.2 Ottenere oggetti

Se Hibernate esegue una richiesta per ottenere dati, non è necessario aprire esplicitamente una transazione. Lo stesso Hibernate lo farà se lo ritiene opportuno: ha le sue impostazioni, così come le impostazioni del server SQL.

Analizzeremo come lavorare con il database. E il più semplice di questi è ottenere un oggetto dal suo ID . Per fare ciò, utilizzare il metodo get()sull'oggetto sessione . La forma generale di tale richiesta:

Class Name = session.get(Class.class, ID);

Esempio:

public User getUserById(Integer id) {
    try (Session session = sessionFactory.openSession()) {
        User user = session.get(User.class, id);
        return user;
    }
}

4.3 Salvare (aggiungere) oggetti

Se desideri salvare il tuo oggetto nel database, verrà eseguita una query a livello SQLINSERIRE. Pertanto, le tue azioni devono essere eseguite come una transazione separata. Inoltre, è meglio usare il metodo persist()dell'oggetto sessione per persistence .

La forma generale di tale richiesta:

session.persist(An object);

Il metodo persist()cambia non solo la base, ma anche l'oggetto stesso. Il fatto è che quando aggiungiamo un oggetto al database, questo oggetto non ha ancora il proprio ID prima di aggiungerlo . Bene, di solito è così, anche se ci sono sfumature. E dopo aver aggiunto l'oggetto ha già un ID .

public boolean saveUser(User user) {
    try (Session session = sessionFactory.openSession()) {
            Transaction transaction = session.beginTransaction();
            session.persist(user);
            transaction.commit();
            return true;
    }
    catch() {
    return false;
   	}
}

L'oggetto Session ha anche un metodo save()che esegue una funzione simile. È solo che il metodo save()è il vecchio standard Hibernate e il metodo persist()è lo standard JPA.

4.4 Eliminazione di oggetti

Se desideri eliminare un oggetto esistente, è molto semplice farlo. Per fare ciò, l'oggetto sessione ha un metodo speciale - remove().

La forma generale di tale richiesta:

session.remove(An object);

E, naturalmente, scriviamo il codice con un esempio:

public boolean removeUser(User user) {
    try (Session session = sessionFactory.openSession()) {
            Transaction transaction = session.beginTransaction();
            session.remove(user);
            transaction.commit();
            return true;
    }
    catch() {
    return false;
   	}
}

Perché è così difficile, chiedi?

Beh, prima di tutto, eventuali modifiche al database hanno sempre conseguenze diverse e non sempre evidenti. E in secondo luogo, a questo oggetto potrebbero essere associati oggetti figlio, ecc. Quindi gli scenari di eliminazione sono spesso non banali.