2016-08-25 3 views
0

Ich schreibe Tests für meine Dao Spring Anwendung. Ich habe herausgefunden, dass, wenn ich nicht gespeicherte Objekte lösche, keine Ausnahme wie erwartet aufgerufen wird, ich habe keine Ahnung warum.Löschen nicht gespeichertes Objekt ruft keine Ausnahme auf

Modell:

@Entity 
public class Ingredient { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 
    private String name; 
    private String condition; 
    private int quantity; 

    public Ingredient() { 

    } 
} 

Die Dao Umsetzung:

@Override 
public void delete(Object o) throws DaoException { 
    try { 
     Session session = mSessionFactory.openSession(); 
     session.beginTransaction(); 
     session.delete(o); 
     session.getTransaction().commit(); 
     session.close(); 
    } catch (Exception ex) { 
     throw new DaoException(ex, String.format("Problem deleting %s object (delete method).", o)); 
    } 
} 

Und mein Test, erwartet DaoException:

@Test 
public void testDeleteNotSavedThrowsDaoException() throws Exception { 
    Ingredient ingredient = new Ingredient("Not saved ingredient","", 1); 
    ingredientDao.delete(ingredient); 
} 
+0

Als eine Randnotiz, würde ich empfehlen, dass Sie Spring Data JPA betrachten. Diese gesamte Methode kann für Sie von gründlich getesteten und weit verbreiteten Bibliotheken automatisch generiert werden. – chrylis

+0

Danke, aber ich muss selbst schreiben CrudDao, sein Teil meines Kurses Test – zzheads

Antwort

4

Hibernate Javadoc für Session#delete(Object) Zustände:

Entfernen Sie eine persistente Instanz aus dem Datenspeicher. Das Argument kann eine Instanz sein, die mit der empfangenden Sitzung assoziiert ist, oder eine vorübergehende Instanz mit einer Kennung, die mit einem bestehenden persistenten Zustand assoziiert ist.

Es ist also kein Fehler, eine transiente Entität zu übergeben (wie Sie es tun). Die Session#delete-Methode deklariert keine Ausnahmen, daher ist nicht definiert, was passiert, wenn Sie eine Entität mit einer ID übergeben, die nicht in der Datenbank vorhanden ist. Wie Sie sehen können - es passiert nichts - haben Sie die Entität angefordert, um nicht in der DB zu existieren, es ist nicht da, um damit zu beginnen, also keinen Grund, eine Ausnahme zu werfen (zumindest nach Hibernate).

Vergleichen Sie dies mit dem grundlegenden SQL DELETE FROM X WHERE ID = Y - dies überprüft nicht, ob ein Datensatz mit ID=Y existiert, wird es in beide Richtungen (Aktualisierung 0 oder 1 Zeilen) erfolgreich sein.

UPDATE nach der Realisierung der vorübergehenden Übergangseinheit hat null ID.

Ich habe in die Quellen von Hibernate 5.2.2 Session gegraben und es scheint, dass, wenn die übergebene Entität keine ID hat, keine DELETE Abfrage sogar auf der Tabelle dieser Entität durchgeführt wird.

Siehe DefaultDeleteEventListener#onDelete(DeleteEvent, Set):

if (ForeignKeys.isTransient(persister.getEntityName(), entity, null, source)) { 
    // yes, your entity is transient according to ForeignKeys.isTransient 
    deleteTransientEntity(source, entity, event.isCascadeDeleteEnabled(), persister, transientEntities); 
    return; 
} 

Jetzt

protected void deleteTransientEntity(
     EventSource session, 
     Object entity, 
     boolean cascadeDeleteEnabled, 
     EntityPersister persister, 
     Set transientEntities) { 
    LOG.handlingTransientEntity(); // Only log it 
    if (transientEntities.contains(entity)) { 
     LOG.trace("Already handled transient entity; skipping"); 
     return; 
    } 
    transientEntities.add(entity); 
    // Cascade deletion to related entities 
    cascadeBeforeDelete(session, persister, entity, null, transientEntities); 
    cascadeAfterDelete(session, persister, entity, transientEntities); 
} 

dies nur "HHH000114: Handling transient entity in delete processing" in den Protokollen gedruckt wird und nichts tun mit dem Unternehmen (aber es wird die Streichung der verbundenen Unternehmen kaskadieren, wenn es sind irgendwelche - nicht dein Fall).

Also noch einmal - es ist in Ordnung, eine transiente Einheit ohne ID zu übergeben - es wird einfach keine DELETE auf der DB laufen.

+0

Ofcourse Methode deklariert werfen DaoException, wenn ein Problem mit der Sitzung passieren: versuchen { Session session = mSessionFactory.openSession(); session.beginTransaction(); session.delete (o); session.getTransaction(). Commit(); session.close(); } catch (Exception ex) { Neue DaoException auslösen (zB String.format ("Problem beim Löschen von% s Objekt (Methode löschen).", O)); } – zzheads

+0

"... oder eine vorübergehende Instanz mit einer Kennung, die dem bestehenden persistenten Zustand zugeordnet ist." Aber wie dieser neue Gegenstand mit BESTEHENDER PERSISTENT-Zustand assoziiert? Die ID des Elements ist null. – zzheads

+0

@zzheads - über die Ausnahme nicht werfen, meinte ich 'Session # delete', nicht dein' Dao # delete'. Über die ID - Ich dachte, die "1" in "neuer Inhaltsstoff (" Nicht gespeicherte Zutat "," ", 1)" ist die ID (Sie haben diesen Konstruktor nicht veröffentlicht), aber jetzt nehme ich an, es ist die Menge, richtig? –

0

Und das war eine Antwort, Adam, es gab keine Ausnahme, weil die ID meines neuen, nicht gespeicherten Artikels null war. Wenn ich ID auf Wert setze, der nicht in der DB beharrte, wurde Ausnahme geworfen.

Verwandte Themen