2016-08-25 3 views
0

Я пишу тесты для своего приложения Dao Spring. Я узнал, что когда я удаляю не сохраненные элементы, исключение не будет вызвано, как я ожидал бы, я понятия не имею, почему.Удалить не сохраненный объект не вызывает исключение

Модель:

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

    public Ingredient() { 

    } 
} 

Dao реализация:

@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)); 
    } 
} 

И мой тест, ожидая DaoException:

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

В качестве побочного примечания я бы рекомендовал вам взглянуть на Spring Data JPA. Весь этот метод может быть автогенерирован для вас тщательно протестированными и широко используемыми библиотеками. – chrylis

+0

Спасибо, но я должен написать собственный CrudDao, его часть моего теста курса – zzheads

ответ

4

Javadoc Hibernate для Session#delete(Object) состояний:

Удалить постоянный экземпляр из хранилища данных. Аргумент может быть экземпляром, связанным с принимающим сеансом или временным экземпляром с идентификатором, связанным с существующим постоянным состоянием.

Так что это не ошибка передачи в переходный объект (как и вы). Кроме того, метод Session#delete не объявляет никаких исключений, поэтому он не определяет, что происходит, когда вы передаете объект с идентификатором, который не существует в БД. Как вы можете видеть - ничего не происходит - вы просили сущность не существовать в БД, ее не стоит начинать, поэтому нет причин бросать исключение (по крайней мере, по Hibernate).

Сравните это с базовым SQL DELETE FROM X WHERE ID = Y - это не проверяет, существует ли запись с ID=Y, она будет успешной в любом случае (обновление 0 или 1 строка).

ОБНОВЛЕНИЕ после реализации пройденного транзитного объекта null ID.

Я выкопал в источники Hibernate 5.2.2 Session, и кажется, что если переданный объект не имеет идентификатора, запрос DELETE выполняется даже в таблице этого объекта.

См 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; 
} 

Теперь

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); 
} 

это будет просто печатать "HHH000114: Handling transient entity in delete processing" в журналах и ничего не делать с объектом (однако, это будет каскадное удаление к связанным лицам, если любые - не ваше дело).

Так что снова - это нормально, чтобы передать переходный объект без идентификатора - он просто не запустит DELETE на БД.

+0

Метод Ofcourse объявляет бросание 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 ("Проблема удаления% s объекта (метод удаления).", O)); } – zzheads

+0

«... или переходный экземпляр с идентификатором, связанным с существующим постоянным состоянием». Но как этот новый предмет ассоциируется с СУЩЕСТВУЮЩИМ СТОРОНЫ? Идентификатор элемента имеет значение NULL. – zzheads

+0

@zzheads - о том, чтобы исключить исключение, я имел в виду 'Session # delete', а не ваш' Dao # delete'. Об ИД - я думал, что '1' в« новом ингредиенте »(« Не сохраненный ингредиент »,« », 1)' является идентификатором (вы не публиковали этот конструктор), но теперь я предполагаю, что это количество, не так ли? –

0

И это был ответ, Адам, не было никакого исключения, потому что id моего нового, не сохраненного элемента был нулевым. Когда я устанавливаю id для значения, которое не сохраняется в исключении БД, было выбрано.

 Смежные вопросы

  • Нет связанных вопросов^_^