Миграция с рукописного персистентного слоя на ORM - PullRequest
9 голосов
/ 19 мая 2010

В настоящее время мы оцениваем варианты перехода с рукописного уровня персистентности на ORM.

У нас есть несколько устаревших постоянных объектов (~ 200), которые реализуют простой интерфейс, подобный этому:

interface JDBC {
    public long getId();
    public void setId(long id);
    public void retrieve();
    public void setDataSource(DataSource ds);
}

Когда вызывается retrieve(), объект заполняется сам, выполняя рукописные SQL-запросы к предоставленному соединению, используя идентификатор, полученный им в установщике (обычно это единственный параметр запроса). Он управляет своими утверждениями, результирующими наборами и т. Д. Сам. Некоторые из объектов имеют специальные разновидности метода retrive(), например retrieveByName(), в этом случае выдается другой SQL.

Запросы могут быть довольно сложными, мы часто объединяем несколько таблиц, чтобы заполнить наборы, представляющие отношения с другими объектами, иногда запросы на соединение выдаются по запросу в конкретном геттере (отложенная загрузка). Таким образом, в основном, мы реализовали большую часть функциональности ORM вручную.

Причиной тому было выступление. У нас очень строгие требования к скорости, и еще в 2005 году (когда был написан этот код) тесты производительности показали, что ни один из основных ORM не был таким быстрым, как рукописный SQL.

Проблемы, с которыми мы сталкиваемся сейчас, заставляющие нас думать об ORM:

  • Большинство путей в этом коде хорошо протестированы и стабильны. Однако некоторые редко используемые коды склонны к результирующему набору и утечкам соединения, которые очень трудно обнаружить
  • В настоящее время мы увеличиваем некоторую дополнительную производительность, добавляя кеширование в наш уровень персистентности, и огромная боль - поддерживать кешируемые объекты вручную в этой установке
  • Поддержка этого кода при изменении схемы БД - большая проблема.

Я ищу совет о том, что может быть лучшей альтернативой для нас. Насколько я знаю, ORM продвинулись за последние 5 лет, так что, возможно, сейчас есть тот, который предлагает приемлемую производительность. Поскольку я вижу эту проблему, нам нужно рассмотреть эти моменты:

  • Найдите способ повторно использовать хотя бы часть написанного SQL для выражения отображений
  • Иметь возможность создавать собственные запросы SQL без необходимости вручную декомпозировать их результаты (т. Е. Избегать ручного rs.getInt(42), поскольку они очень чувствительны к изменениям схемы)
  • Добавить неинтрузивный слой кэширования
  • Сохранить показатели производительности.

Есть ли какие-либо рамки ORM, которые вы могли бы по этому поводу порекомендовать?

ОБНОВЛЕНИЕ Чтобы понять, о каких показателях производительности мы говорим:

  • Бэкэнд-база данных - TimesTen, база данных в памяти, которая работает на том же компьютере, что и JVM
  • Мы обнаружили, что изменение rs.getInt("column1") на rs.getInt(42) приносит увеличение производительности, которое мы считаем значительным.

Ответы [ 6 ]

5 голосов
/ 19 мая 2010

Если вам нужен стандартный уровень персистентности, который позволяет создавать собственные запросы SQL, рассмотрите возможность использования iBATIS. Это довольно тонкое отображение между вашими объектами и SQL. http://ibatis.apache.org/

Для кэширования и ленивых объединений, Hibernate может быть лучшим выбором. Я не использовал iBATIS для этих целей.

Hibernate обеспечивает большую гибкость, позволяя вам задавать определенные значения по умолчанию для отложенной загрузки при прохождении графа объекта, а также предварительно извлекать данные с помощью запросов SQL или HQL к содержимому вашего сердца, когда вам нужно более известное время загрузки. Тем не менее, процесс преобразования будет сложным для вас, поскольку он имеет довольно высокую планку для входа с точки зрения обучения и конфигурации. Аннотации сделали это проще для меня.

Два преимущества, о которых вы не упомянули при переходе на стандартную среду: (1) устранение ошибок становится легче, когда у вас есть множество сайтов и форумов, которые могут вас поддержать. (2) новые сотрудники дешевле, проще и быстрее.

Удачи в решении вопросов производительности и удобства использования. Компромиссы, на которые вы указываете, очень распространены. Извините, если я проповедую Евангелие.

4 голосов
/ 22 мая 2010

Для большинства ваших запросов я бы выбрал режим гибернации. Он широко используется, хорошо документирован и в целом эффективен. Вы можете перейти на рукописный SQL, если hibernate не производит достаточно эффективные запросы. Hibernate дает вам большой контроль при указании имен таблиц и столбцов, на которые отображаются объекты домена, и в большинстве случаев вы можете ретро-адаптировать его к существующей схеме.

  • Найдите способ повторно использовать хотя бы часть написанного SQL для выражения отображений Отображения выражены в JPA с использованием аннотаций. Вы можете использовать существующий SQL в качестве руководства при создании JPQL запросов.

  • Добавить неинтрузивный слой кэширования

Кэширование в спящем режиме происходит автоматически и прозрачно, если только вы не решите принять участие Вы можете пометить объекты как доступные только для чтения или исключить их из кэша, чтобы контролировать, когда изменения сбрасываются в базу данных (конечно, внутри транзакции - автоматическое использование пакетной обработки повышает производительность, когда сетевая задержка является проблемой.)

  • есть возможность оформить родной SQL-запросы без необходимости вручную разложить их результаты (т.е. избегайте ручного rs.getInt (42), поскольку они очень чувствительны к изменениям схемы)

Hibernate позволяет писать SQL и сопоставлять его с вашими сущностями. Вы не имеете дело с ResultSet напрямую - hibernate заботится о деконструкции вашей сущности. См. Chpt 16, собственный SQL в руководстве по гибернации.

  • Поддержка этого кода при изменении схемы БД - большая проблема.

Управление изменениями схемы все еще может быть проблематичным, поскольку теперь у вас фактически есть две схемы - схема базы данных и отображение JPA (схема объекта). если вы решите позволить hibernate сгенерировать схему БД и переместить туда ваши данные, вы больше не будете нести прямую ответственность за то, что входит в базу данных, и поэтому вы столкнетесь с управлением автоматическими изменениями в сгенерированной машиной схеме. Есть инструменты, которые могут помочь, такие как dbmigrate и liquibase , но это не прогулка в парке. И наоборот, если вы управляете схемой БД вручную, то вам придется тщательно перестраивать свои сущности, аннотации JPA и запросы, чтобы учесть изменения схемы. Добавление столбцов и новых объектов является относительно тривиальным, но более сложные изменения, такие как изменение одного свойства для набора свойств или перестройка иерархии объектов, повлекут за собой значительно более обширные изменения. Легкого выхода из этого не существует - либо db, либо hibernate - это «ведущий», который решает схему, и когда одно меняется, другой должен следовать. Изменения в коде не так уж и плохи - по моему опыту, это трудная миграция данных. Но это основная проблема с базами данных, которая будет присутствовать в любом выбранном вами решении.

Итак, чтобы подвести итог, я бы выбрал режим гибернации и использовал интерфейс JPA.

3 голосов
/ 19 мая 2010

Я недавно пробежался по куче Java ORM и не придумал ничего лучше, чем Hibernate. Производительность Hibernate может помочь вам достичь поставленных целей.

Многие люди думают, что переход на Hibernate сделает все таким замечательным, но на самом деле он просто переносит ряд проблем из запросов JDBC в настройку Hibernate. Прочитайте кучу книг или (лучше) наймите «спящего парня», чтобы прийти и помочь.

Во время вашего рефакторинга я бы порекомендовал использовать JPA, чтобы вы могли отключить и снова подключить нового поставщика сохраняемости, когда появится следующая большая вещь (или вы перейдете в Oracle)

2 голосов
/ 25 мая 2010

Вам действительно нужно мигрировать? Что заставляет вас двигаться? Есть ли какая-то НАСТОЯЩАЯ потребность здесь или кто-то просто изобретает работу («Архитектор астронавтов»)?

Я согласен с приведенными выше ответами - если вам нужно переехать - Hibernate или iBatis - хороший выбор. iBatis особенно, если вы хотите оставаться «ближе» к SQL.

1 голос
/ 02 декабря 2010

Здесь уже есть много полезных советов, которые я не буду повторять. Единственное, что я не заметил, предположило, что это может сработать, - это кэширование справочных данных в памяти.

В прошлом я делал немало, и это экономит много времени. Если у вас есть большое количество довольно статических справочных таблиц, загрузите их все в память во время запуска и обновляйте их каждые пару минут. Таким образом, вы не будете снова и снова использовать БД для данных, которые никогда не меняются.

1 голос
/ 26 мая 2010

Если вам нужно больше производительности: удалите базу данных (для работы в режиме онлайн) и работайте напрямую с постоянством. Добавление кэширования не поможет вам с базой данных TimesTen, оно просто добавляет дополнительную копию (замедляет работу).

Возможно, вы захотите взглянуть на GemFire.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...