|
|
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
БД - Oracle, создан сиквенс и привязан аннотацией к объекту. При создании нового java-объекта поле id изначально равно нулю. Когда объект сохраняется через save(obj) метод отрабатывает успешно и генерируется id отличный от нуля, хотя одно из полей в таблице (назовем его условно field) имеет уникальный индекс. Затем происходит выход из транзакции (из метода, помеченного аннотацией @Transactional). В этот момент выбрасывается исключение нарушения ограничения уникальности field, транзакция откатывается. Сгенерированный id остается в java-объекте, что неприятно, приходится "вручную" его обнулять. Вопрос. Почему исключение не возникло на самом save(obj)? То есть хибер закэшировал вставку?! Ведь если зайти в pl/sql developer и вручную провести подобную операцию, то исключение появится сразу, а не при попытке зафиксировать транзакцию. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 15:29 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaПри создании нового java-объекта поле id изначально равно нулю. Почему не null? myauchaСгенерированный id остается в java-объекте, что неприятно, приходится "вручную" его обнулять. А вот это интересный факт. myauchaВопрос. Почему исключение не возникло на самом save(obj)? Потому что Session aka EntityManager aka Unit of Work ещё называется кешем первого уровня. Это такая оптимизация, чтобы на каждый пук не генерировать SQL запрос. Для особо торопливых есть метод flush() myauchaТо есть хибер закэшировал вставку?! Конечно. myauchaВедь если зайти в pl/sql developer и вручную провести подобную операцию, то исключение появится сразу, а не при попытке зафиксировать транзакцию. Ведь ORM и PL/SQL это не одно и то же? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 15:34 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, По поводу отката id вот тут хорошо описано http://stackoverflow.com/questions/20636144/entity-state-and-entity-id-value-in-jpa-hibernate-after-rollback JPA требует такого поведения Но хибер позволяет включить опцию hibernate.use_identifier_rollback ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 15:38 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
Пока читаю про состояния объекта попутно задам уточняющие вопросы BlazkowiczmyauchaПри создании нового java-объекта поле id изначально равно нулю. Почему не null?Объявлял id как int, поэтому и ноль. Есть какие-то предубеждения против использования простых типов в качестве идентификаторов?! BlazkowiczПо поводу отката id вот тут хорошо описано http://stackoverflow.com/questions/20636144/entity-state-and-entity-id-value-in-jpa-hibernate-after-rollback JPA требует такого поведения Но хибер позволяет включить опцию hibernate.use_identifier_rollbackОпция use_identifier_rollback не помогла. Добавлял ее, как в таком варианте - hibernate.use_identifier_rollback, так и без префикса - use_identifier_rollback. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 16:58 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaЕсть какие-то предубеждения против использования простых типов в качестве идентификаторов?! Конечно. БД разрешает вам хранить 0 в колонке первичного ключа. А вот null не разрешит. myauchaв таком варианте - hibernate.use_identifier_rollback, так и без префикса - use_identifier_rollback. Тут я ничего не могу сказать. Надо посмотреть как он используется в исходнике. И куда вы его вообще пихали. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 17:14 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
BlazkowiczmyauchaЕсть какие-то предубеждения против использования простых типов в качестве идентификаторов?! Конечно. БД разрешает вам хранить 0 в колонке первичного ключа. А вот null не разрешит.Пока не убедили. Если приложение выполняет проверку на id == 0 и отправляет объект в зависимости от результата либо на save(obj), либо на update(obj), то риска вроде бы нет?! myauchaв таком варианте - hibernate.use_identifier_rollback, так и без префикса - use_identifier_rollback. Тут я ничего не могу сказать. Надо посмотреть как он используется в исходнике. И куда вы его вообще пихали.[/quot]В статье (да и в документации к настройке это прописано) высказывались предположения о том, что эта настройка работает только для delete. Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Вы-то сами как поступаете в проектах с идентификаторами объектов, когда выполняется Вставка и нарушаются ограничения, приводящие к откату? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 17:28 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaто риска вроде бы нет?! Assumption is the mother of all fuck ups. 1) Целостность данных БД нужно обеспечивать средствами БД, а не ORM. 2) Сторонние библиотеки (например Spring Data) не в курсе деталей вашего Hibernate маппинга и опираются на общие практики, такие как проверку id на null. 3) В случае присвоения кем-то значения 0 по ошибке (генератор сломался или ещё какой лисопед самоуправством занялся) вы не сможете отличить его от значения 0 по-умолчанию. 4) Некоторые бд имеют по-умолчанию инкремент от 0. Что может выйти боком, когда вдруг понадобится портировать с Oracle. Остаётся вопрос. Почему бы сразу не убрать грабли? myauchaВы-то сами как поступаете в проектах с идентификаторами объектов, когда выполняется Вставка и нарушаются ограничения, приводящие к откату? Обычно, я про этот объект забываю. Он невалидный. Зачем мне его состояние? Нужно сформировать новый. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 17:41 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaВы-то сами как поступаете в проектах с идентификаторами объектов, когда выполняется Вставка и нарушаются ограничения, приводящие к откату?Обычно, я про этот объект забываю. Он невалидный. Зачем мне его состояние? Нужно сформировать новый.[/quot]Вколачивал пользователь данные в форму, они пришли в контроллер в виде объекта, объект семантически верный, пытаемся его сохранить, но ограничения в БД не позволили это сделать. Логично передать объект пользователю обратно на доработку. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 18:04 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaВколачивал пользователь данные в форму, они пришли в контроллер в виде объекта, объект семантически верный, пытаемся его сохранить, но ограничения в БД не позволили это сделать. Логично передать объект пользователю обратно на доработку. Во-первых, объекты на UI и в ORM совпадают только в простейших случаях. При большой модели предметной области оказывается очевидным что объекты на UI нужны совсем не такие как в ORM. Во-вторых почему мы в UI потеряли данные, если мы их ещё не сохранили? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 18:14 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, 1.Руками обнулять. 2.Первой же строчкой в сервисе делать копию того, что пришло. 3.Dto и им подобное. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 18:50 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
авторПри большой модели предметной области оказывается очевидным что объекты на UI нужны совсем не такие как в ORM. Вопрос нахрена тогда вообще нужен ORM? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 18:52 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, Значит на sql.ru дураки. Т.к. в форуме если объект не прошел, то он потерян. Хотя написать за свой счет можно что угодно. Заказчик только рад будет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 19:02 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
BlazkowiczВо-первых, объекты на UI и в ORM совпадают только в простейших случаях. При большой модели предметной области оказывается очевидным что объекты на UI нужны совсем не такие как в ORM. Во-вторых почему мы в UI потеряли данные, если мы их ещё не сохранили?В общем понятно. В простом случае (когда объект ввода является объектом сохранения) тот объект, который приходит в контроллер надо копировать и сохранять в базу уже копию. Если транзакция завершается откатом, то копию забываем и передаем пользователю для повторного редактирования оригинал. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 19:05 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, Разве при райзе у вас объект куда то пропал? 1. Правило в веб - не допускать райзе. Откуда оно? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 19:09 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
no56892Вопрос нахрена тогда вообще нужен ORM? Ну, если у вас кроме UI и БД других слоёв нет, то в вашей архитектуре, вероятно не нужен. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 20:13 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaВ общем понятно. В простом случае (когда объект ввода является объектом сохранения) тот объект, который приходит в контроллер надо копировать и сохранять в базу уже копию. Если транзакция завершается откатом, то копию забываем и передаем пользователю для повторного редактирования оригинал. Обратите ещё внимание на такую фичу hibernate как dirty check. Описанный вами вариант не единственный. Например можно контроллер научить заполнять уже загруженный объект. А не использовать тот, который он создал. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2016, 20:16 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
Еще один вопрос. Поскольку он связан с существующим, то не буду создавать отдельную тему. Если происходит сохранение объекта в методе контроллера через вызов service.save(obj). Метод используется для создания нового объекта или изменения существующего. Известно, что при сохранении могут возникнуть две ошибки, которые должны быть обработаны. Первая ошибка ObjAlreadyExists возникает когда объект с указанным именем уже существует в базе, вторая ObjNotFound - объект не найден в базе (например, в результате оптимистичного метода редактирования и последующего сохранения). Естественно возникает желание сделать нечто такое: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. В самом service.save вызывается dao.save, в нем генерируются исключения, но не ObjAlreadyExists или ObjNotFound, а другие унаследованные от DataAccessException или от RuntimeException. Причем, реализация dao может быть выполнена для jdbc, для hibernate или для чего-то еще. В каждой реализации исключения будут разные (некоторые могут и совпадать). Есть желание трансформировать их в ObjAlreadyExists и ObjNotFound. В документации Spring указано, что потомки DataAccessException - это преобразованные (например, из jdbc или hibernate исключений) runtime-исключения, и что Spring рекомендует использовать именно их вместо нудных описаний throws в методах. Предположим, их доводы убедительны плюс не хочется засорять код dao-реализаций конструкциями try/catch и генерированием соответствующих ObjAlreadyExists и ObjNotFound-исключений. Поэтому объявляю ObjAlreadyExists и ObjNotFound наследниками runtime-исключений и пытаюсь их преобразовать... Вопрос где лучше сделать такое преобразование?! Если сделать отдельный метод в контроллере, обозначив его аннотацией @ExceptionHandler, то после преобразования уже, насколько я понимаю, не получится вернуться в try/catch obj = service.save(obj) и продолжить оперировать объектами obj или bindingResult. То есть, существует ли способ перехватить исключение, выполнить преобразование и продолжить подниматься по цепочке вызовов. Насколько я понял, разные варианты реализации обработки - @ControllerAdvice или интерфейс HandlerExceptionResolver - это все обработка упущенных (необработанных) исключений. А нужен некий interceptor. Может вообще надо делать по-старинке (по крайней мере для данного примера) - в dao перехватывать исключения и генерировать ObjAlreadyExists и ObjNotFound, унаследованные от обычного Exception. И протянуть (посредством throws-описания в заголовке метода) их через dao.save и service.save, обязав к тому же пользователя предусмотреть обработку try/catch?! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.09.2016, 18:02 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaЕще один вопрос. Поскольку он связан с существующим, то не буду создавать отдельную тему. В подфоруме Java все вопросы связаны одной технологией. Ваш новый вопрос к первоначальному ведь не относится совершенно. myauchaПервая ошибка ObjAlreadyExists возникает когда объект с указанным именем уже существует в базе У объектов нет имён. И кстати, в случае ORM говорят о сущностях (entity), потому как два объекта могут быть одной сущностью, например. myauchaвторая ObjNotFound - объект не найден в базе (например, в результате оптимистичного метода редактирования и последующего сохранения). Вот этого я вообще не понял. Как NotFound связан с оптимистичной блокировкой? myauchaВ самом service.save вызывается dao.save, в нем генерируются исключения, но не ObjAlreadyExists или ObjNotFound DAO для ORM почти бесполезны. Обычно они вырождаются в Repository. myaucha, а другие унаследованные от DataAccessException или от RuntimeException. Если вам это критично, то нужно для каждой реализации написать обработчик и конвертор исключений. http://docs.spring.io/autorepo/docs/spring/4.2.x/spring-framework-reference/html/dao.html myauchaПричем, реализация dao может быть выполнена для jdbc, для hibernate или для чего-то еще. Я надеюсь вы не используете одну и ту же базу для JDBC и ORM? myauchaВ документации Spring указано, что потомки DataAccessException - это преобразованные (например, из jdbc или hibernate исключений) runtime-исключения, и что Spring рекомендует использовать именно их вместо нудных описаний throws в методах. Зачем вы всё в кучу мешаете? DataAccessException это одно. Runtime vs Checked Exception это отдельная тема. myauchaВопрос где лучше сделать такое преобразование?! Очевидно, что в DAO. myauchaЕсли сделать отдельный метод в контроллере, обозначив его аннотацией @ExceptionHandler, то после преобразования уже, насколько я понимаю, не получится вернуться в try/catch obj = service.save(obj) и продолжить оперировать объектами obj или bindingResult. То есть, существует ли способ перехватить исключение, выполнить преобразование и продолжить подниматься по цепочке вызовов. Насколько я понял, разные варианты реализации обработки - @ControllerAdvice или интерфейс HandlerExceptionResolver - это все обработка упущенных (необработанных) исключений. А нужен некий interceptor. Ну, логично что это можно сделать через AOP. Но только не на уровне MVC, когда уже поздно обрабатывать ошибку обращения к данным. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.09.2016, 18:28 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, Где ты взял эти исключения? У тебя весь роман текста построен на этих двух именах. Может SaveOrUpdate (объект ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.09.2016, 19:00 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
В итоге получилось следующее Исключения Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Контроллер Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Сервис Код: java 1. 2. 3. 4. 5. 6. 7. 8. DAO (JDBC) Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. DAO (Hibernate) Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. Особенности: Поскольку исключения UserAlreadyExists и UserNotFound рантаймовские, то при написании в контроллере userService.save не будет требования их обработки - это минус. Зато не надо тянуть их через слои и прописывать атрибут rollbackFor для @Transactional, чтобы откатывалась транзакция. Странности: В DAO для jdbc перехватывается ошибка spring-а DuplicateKeyException, то есть уже после преобразования. В DAO же для hibernate перехватываются хибернетовские исключения ConstraintViolationException и StaleStateException. Если выйти из хибернетовского save, то ошибка останется по-прежнему ConstraintViolationException. Если выйти из сервисного save, то исключение преобразуется в spring-овое. Если теперь прописать в настройках Код: xml 1. , то В DAO для hibernate по-прежнему перехватываются хибернетовские исключения, на выходе они преобразуются в spring-овые, при выходе из транзакции как и раньше - spring-овые. Сейчас, пока писал, понял почему для JDBC сразу получаю spring-овое - потому что через jdbcTemplate работаю. Так что все понятно. Ну и flush пришлось все-таки написать, потому что иначе ошибку можно будет отловить только на выходе из транзакции (то есть в контролере), а тогда уже поздно - выходить из сервиса ошибка должна уже преобразованной. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 11:19 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaUserAlreadyExists и UserNotFound где взял эти исключения? Их не будет при сохранении объекта хибером. 19618727 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 11:28 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, вот это DuplicateKeyException - с чего вдруг у тебя появится? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 11:32 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, У тебя какая-то фигня с настройкой Spring + hibernate походу. DuplicateKeyException это если только делать persist с уже проставленным id - то возможно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 11:49 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
no56892myaucha, У тебя какая-то фигня с настройкой Spring + hibernate походу. DuplicateKeyException это если только делать persist с уже проставленным id - то возможно. +1 Что-то он неделю борется как Дон кихот с этой проблемой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 11:55 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
В хибере (ОРМ) всё просто: - мы знаем какой (новый или существующий) мы правим и указываем хиберу - хибер сам знает что делать чтобы исключений не было - если СПЕЦИАЛЬНО указать ему что не надо затирать изменения соседом, то будет исключение всего одно по оптимистической блокировке. Всё. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 11:58 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
Основная идея - привести DAO(JDBC) и DAO(Hibernate) к общему знаменателю, чтобы при подмене одного на другой не пришлось ничего меня в сервисе и контроллере. Для этих целей введены два новых исключения, расширяющие стандартные спринговые и более точно характеризующие ошибки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 12:29 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaОсновная идея - привести DAO(JDBC) и DAO(Hibernate) к общему знаменателю, чтобы при подмене одного на другой не пришлось ничего меня в сервисе и контроллере. Для этих целей введены два новых исключения, расширяющие стандартные спринговые и более точно характеризующие ошибки. это у вас программисты сами себе такие задачи могут ставить? По задаче - "Эх, нету на вас руководителя проекта со сроками"). По сабжу я привёл выше: У DAO(Хибера) нет ошибок в виде райзе в стандартной многопользовательской работе (веб проект). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 13:15 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
Petro123У DAO(Хибера) нет ошибок в виде райзе в стандартной многопользовательской работе (веб проект).А теперь переведите эту фразу на русский? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 13:24 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, может с тебя начнём? Я спросил, при каком юз кейсе или ВИ у тебя происходит райзе. Или у тебя академическая задача? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 13:38 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, насколько в курсе, спринг УЖЕ сделал вместо SQLExeption свои : ------------------ CannotAcquireLockException CannotSerializeTransactionException CleanupFailureDataAccessException ConcurrencyFailureException DataAccessException DataAccessResourceFailureException DataIntegrityViolationException DataRetrievalFailureException DeadlockLoserDataAccessException EmptyResultDataAccessException IncorrectResultSizeDataAccessException IncorrectUpdateSemanticsDataAccessException InvalidDataAccessApiUsageException InvalidDataAccessResourceUsageException OptimisticLockingFailureException PermissionDeniedDataAccessException PessimisticLockingFailureException TypeMismatchDataAccessException UncategorizedDataAccessException ----------- это мало? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 13:43 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
Petro123, Я не отвечаю, когда обращение идет на ты, так что закончили дискуссию ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 13:43 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaЯ не отвечаю, когда обращение идет на ты, так что закончили дискуссию О, как. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 13:51 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myaucha, вики)) авторВ русском языке обращение «на вы» постепенно вошло в употребление с XVIII века из-за сильного влияния французского языка и культуры, прежде всего в кругах аристократии. Существуют теории, что исконно «вы» было обращением к врагу. Удачи! Работайте! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 13:55 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
Это не теория: "Иду на вы" - послание князя Святослава, которому было лень гоняться за разрозненными отрядами ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2016, 16:47 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaОсновная идея - привести DAO(JDBC) и DAO(Hibernate) к общему знаменателю, чтобы при подмене одного на другой не пришлось ничего меня в сервисе и контроллере. Для этих целей введены два новых исключения, расширяющие стандартные спринговые и более точно характеризующие ошибки. правильно. только это не расширение. это изоляция слоев, чтобы ожидаемые DAO-исключения (конкурентный доступ, уникальность, FK и т.п.) не вылезали туда, куда им не стоит ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.09.2016, 19:48 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
fsharp_fsharpправильно. только это не расширение. это изоляция слоев, чтобы ожидаемые DAO-исключения (конкурентный доступ, уникальность, FK и т.п.) не вылезали туда, куда им не стоитВне зависимости от того, как это назовешь стандартная трансляция исключений в spring-е не до конца продумана. Приведу пример. Предположим ни в DAO, ни в сервисе я не перехватываю исключений (то есть не подменяю своими, а использую стандартные спринговые) и делаю обработчик в контролере. Пусть у нас есть два DAO - для JDBC и для Hibernate. Пусть есть некая таблица в БД, в которой помимо первичного ключа еще два поля (например, user_name и email) должны быть уникальны. Тогда при нарушении уникальности на поле user_name в контроллер вернутся следующие исключения (предполагается, что имена ограничений в БД имеют семантический смысл и могут быть распарсены): DAO-JDBC: org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [insert into user_t (user_id, user_name, password, role_id, birthday, email) values (seq_id.nextval, ?, ?, ?, ?, ?)]; ORA-00001: нарушено ограничение уникальности (THIRD.USER$U$USER_NAME); nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-00001: нарушено ограничение уникальности (THIRD.USER$U$USER_NAME) DAO-Hibernate org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [THIRD.USER$U$USER_NAME]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement Теперь на основе полученной информации мы хотим создать единый обработчик ошибок. Поскольку DuplicateKeyException наследует от DataIntegrityViolationException, то в обработчике надо предусмотреть обработку только DataIntegrityViolationException. Контроллеру, чтобы правильно вернуть пользователю информацию об ошибке (комментарий к полю формы ввода user_name или email), надо идентифицировать строку THIRD.USER$U$USER_NAME (для email строка будет THIRD.USER$U$EMAIL) как ограничение и разобрать ее. Для DAO-Hibernate это сделать просто - надо опуститься на уровень ниже и получить org.hibernate.exception.ConstraintViolationException, в котором заботливо предусмотрен метод getConstraintName. В DAO-Jdbc такой возможности нет и надо доставать имя ограничения прямо из сообщения. Спрашивается, что мешало создать метод (поле) getConstraintName в спринговом DataIntegrityViolationException и при реализации преобразований исключений для jdbc сделать его наполнение, раз уж эти исключения считаются стандартными?! Раз нет такой возможности, то в едином обработчике надо писать код, который бы еще проверял, а сидит ли на уровне ниже Hibernet-овское исключение или JDBC-ное (или еще какое-то), что уже криво. А с учетом того, что помимо реализации DAO может меняться и СУБД, то могут и еще какие-то проблемы всплыть. Получается, чтобы сделать обработчик ошибок единым, надо вообще всегда брать getRootCause() и парсить исходную ошибку. И тогда от спринговых ошибок остается единственная польза - они рантаймовские. Понятно, что они поделены на группы и при анализе ошибки можно отделить DataIntegrityViolationException, например, от OptimisticLockingFailureException, но пример выше показывает, что этого недостаточно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.09.2016, 11:35 |
|
||
|
Hibernate - cохранение объекта
|
|||
|---|---|---|---|
|
#18+
myauchaПусть у нас есть два DAO - для JDBC и для Hibernate тема про хибер? Тогда при чём JDBC, да ещё попытка одного кода для JDBC и для ОРМ. Кто на ком стоял? Тебе бы тему переименовать чтобы не пудрить мозги: Академико-теоретическая задача про универсальный код в DAL. myauchaА с учетом того, что помимо реализации DAO может меняться и СУБД, то могут и еще какие-то проблемы всплыть. и программисты могут меняться. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.09.2016, 12:22 |
|
||
|
|

start [/forum/topic.php?all=1&fid=59&tid=2123753]: |
0ms |
get settings: |
10ms |
get forum list: |
17ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
90ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
89ms |
get tp. blocked users: |
2ms |
| others: | 236ms |
| total: | 467ms |

| 0 / 0 |
