|
Java форум JavaTalks форум программистов
|
|
|
|
| Предыдущая тема :: Следующая тема |
| Автор |
Сообщение |
plazman : 43 Новичок
|
Фев 17, 2012 13:05 |
|
|
Например, есть у нас сущность
Partner (id, code, name, description, type)
И нам нужно грузить поля по необходимости, то есть в разных случаях по разному.
Вариант lazy и не lazy не прокатывает, так как это чёрно-белый вариант, а нежен цветной
Например, какие варианты имеются ввиду в данном случае
1. Табличная форма: id, code, name, type (без description) HEADER_LEVEL
2. Форма для редактирования: id, code, name, type, description (всё) DETAIL_LEVEL
3. Комбобоксы: id, code, name (без description, type) LINK_LEVEL
Может это уже реализовано в Hibernate ???
Это простой пример, но иногда (если не всегда) сущности обрастают кучами связей и тянут за собой тонны ненужного мусора. |
|
|
|
 |
Староверъ : 7629 Ктапубеп Откуда: Elfland
|
Фев 17, 2012 14:13 |
|
|
Похоже на ситуацию, когда нужно создать какой-то SearchRequest с набором полей, затем в зависимости от того какие из них там указаны как EAGER, устанавливать соответствующий fetch при создании критерии. _________________ JTalks Open Source Project, JT Webinars, JT Interview |
|
|
|
 |
Skipy : 4805 Я тут живу! Откуда: Москва, Россия
|
Фев 17, 2012 14:17 |
|
|
| plazman писал(а): |
| Это простой пример, но иногда (если не всегда) сущности обрастают кучами связей и тянут за собой тонны ненужного мусора. |
Добро пожаловать в реальный мир. Это фундаментальная проблема ORM как подхода. Удовлетворительного решения не имеет. _________________ С уважением,
Евгений aka Skipy
www.skipy.ru
P.S. Я НЕ решаю задачи ЗА других! |
|
|
|
 |
Староверъ : 7629 Ктапубеп Откуда: Elfland
|
Фев 17, 2012 14:28 |
|
|
| Цитата: |
| Удовлетворительного решения не имеет. |
Хм.. самое простое решение - сделать несколько методов с разными фетч стратегиями. Та же проблема будет и в чистом JDBC, никакой разницы в данной ситуации нет.
Еще один вариант - замапить несколько классов на одни и те же таблицы по-разному, это для еще более сложных решений.
И третий вариант, для самых сложных проблем, - создать View, которая аккумулирует только нужные данные для данного вида запросов и замапить класс на нее. _________________ JTalks Open Source Project, JT Webinars, JT Interview |
|
|
|
 |
plazman : 43 Новичок
|
Фев 17, 2012 17:06 |
|
|
То есть проблема решается путём создания новых классов ?
На каждый случай свой класс ?
PartnerLink - LINK_LEVEL
PartnerHeader - HEADER_LEVEL
Partner - DETAIL_LEVEL
В каждом классе свои поля
Или я не правильно понял мысль ? |
|
|
|
 |
plazman : 43 Новичок
|
Фев 17, 2012 17:07 |
|
|
to Староверъ
Если не затруднит, можно примерчик.
Я имел ввиду пример на это:
| Цитата: |
| сделать несколько методов с разными фетч стратегиями |
Спасибо. |
|
|
|
 |
plazman : 43 Новичок
|
Фев 17, 2012 17:28 |
|
|
И ещё мысли вслуг...
А чем вообще вызвано, что в Hibernate или других ORM так болезненно относятся к загрузке полей по требованию БЕЗ ИЗМЕНЕНИЯ при этом маппинга, создания отдельных классов, методов и т.д.
Может это с чем то связано....как то совсем не верится, что это трудно в реализации...значит какая то причина есть.
Хотелось бы видеть что то типа...
| Код: |
/* Загрузить только поля code, name */
EntityManager.select(Partner.class, "code, name")
...
/* Загрузить только поля code, name и все поля для свойства type кроме поля description */
EntityManager.select(Partner.class, "+code, name, type.* -type.description")
|
Просто куча народу из-за такой вот "МЕЛОЧИ" начинают создавать свои ORM... |
|
|
|
 |
Староверъ : 7629 Ктапубеп Откуда: Elfland
|
Фев 17, 2012 19:50 |
|
|
Нужно просто понимать, ничего тут сложного нет. Если подумать, то как еще должен работать ORM? Какие предложения?
Во многих ситуациях просто ленивая инициализация дложна помочь, ты уверен, что ты понимаешь что и зачем делаешь? Может и тебе ленивая загрузка поможет?
Примеры не знаю какие привести - я предоставил несколько рецептов, вроде как там больше нечего описывать. Разные фетч стратегии - значит использование JOIN в HQL или EagerFetch в CriteriaAPI, что приводит к методам типа getUser(), getUserWithDogs(), getFullUser(). _________________ JTalks Open Source Project, JT Webinars, JT Interview |
|
|
|
 |
Vermut : 1063 Завсегдатай Откуда: Ростов-на-Дону
|
Фев 17, 2012 22:17 |
|
|
| Skipy писал(а): |
| plazman писал(а): |
| Это простой пример, но иногда (если не всегда) сущности обрастают кучами связей и тянут за собой тонны ненужного мусора. |
Добро пожаловать в реальный мир. Это фундаментальная проблема ORM как подхода. Удовлетворительного решения не имеет. |
Это проблема вообще никакого отношения к ORM не имеет. Когда сущности начинают беспорядочно обрастать связями, нужно идти в книжный магазин брать книгу Эрика Эванса "Предметно-Ориентированное проектирование" и читать главы связанные с дистиляцией модели до тех пор пока не наступит просветление.
Что касается управления ленивой загрузкой то Старовер уже всё написал, нужную fetch стратегию легко варьировать выбирая необходимую в каждый конкретный момент вермени, при формировании запроса. Правда я погуглил минут 10 и не нашел как это сделать в JPA, возможно придеться спуститься на уровень родной ORM которая у Вас заюзана как реализация JPA, я правда никогда EntityManager не пользовался возможно задать тип фетча динамически можно и средствами самого JPA, но в принципе если это и нельзя, не вижу в этом ничего плохого чтобы использовать аннотации JPA на энтитях но вместо EntityManager пользоваться обычной Hibernate Session. _________________ Познакомлюсь с привлекательной Ростовчанкой для совместного изучения Java |
|
|
|
 |
plazman : 43 Новичок
|
Фев 18, 2012 10:13 |
|
|
Ну как я и подозревал...
элементарные вещи нельзя реализовать на популярном ORM аля Hibernate....
Мда...лучше 2 месяца потерять... на создание ORM, но потом за час долететь...чем всю жизнь мучиться |
|
|
|
 |
Vermut : 1063 Завсегдатай Откуда: Ростов-на-Дону
|
Фев 18, 2012 11:10 |
|
|
Как человек уже написавший свою ORM Вам этого делать не советую. Если этим занятием и стоит заняться только в очень специфических случаях, я например писал свою как часть инструмента трансформации и синхронизации данных между разными СУБД, а в обычных проектах использую хибернейт.
Для хибернейта Ваш случай предельно простой. Допустим изначально связь между юзером и его правами ленивая, но появился юзкейс в котором права нужно загрузить сразу вмести с юзером одним SQL запросом просто приджойнив их. Тогда на Criteria API это будет так:
| Код: |
User user = (User) session.createCriteria(User.class)
.setFetchMode("permissions", FetchMode.JOIN)
.add( Restrictions.idEq(userId) )
.uniqueResult();
|
ТеперЬ вам нужно разобраться как аналогичное делать с EntityManager. _________________ Познакомлюсь с привлекательной Ростовчанкой для совместного изучения Java |
|
|
|
 |
Vermut : 1063 Завсегдатай Откуда: Ростов-на-Дону
|
Фев 18, 2012 11:36 |
|
|
Собственно в JPA тоже фетч стратегии можно настраивать, всё что нужно это прочитать документацию, пример аналогичный предидущему только для JPA:
| Код: |
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery query = cb.createQuery(User.class);
Root<User> root = query.from(User.class);
query.where(cb.equal(root.get("id"), userId));
root.fetch("permissions", JoinType.LEFT);
User user = (User) query.getSingleResult();
|
Так что вместо написания собственной ORM читайте документацию в ней всё написано. _________________ Познакомлюсь с привлекательной Ростовчанкой для совместного изучения Java |
|
|
|
 |
Vermut : 1063 Завсегдатай Откуда: Ростов-на-Дону
|
Фев 18, 2012 12:15 |
|
|
Ну а собственно как это все дело оформить красиво то можно так:
| Код: |
public class MediaDaoImpl implements MediaDao {
...
@Override
List<Single> findSingleByCriteria(SingleSearchCriteria singleCriteria) {
Criteria criteria = session.createCriteria(Single.class);
if (singleCriteria.joinArtist()) {
criteria.setFetchMode("artist", FetchMode.JOIN)
}
if (singleCriteria.joinAlbum()) {
criteria.setFetchMode("album", FetchMode.JOIN)
}
if (singleCriteria.getTitlePattern() != null) {
criteria.addRestrictions(Restirctions.ilike("title"), singleCriteria.getTitlePattern())
}
... настройка других параметров запроса
return criteria.list();
}
...
}
|
Пример показывает как искать песни с возможным динамическим выбором подгрузки артиста, альбома.
Так что Skipy попробуйте здесь найти фундаментальную проблему ORM Всё вроде объектно-ориентированно и прозрачно, какой критерий сформирует клиент этого DAO такой результат и получит. _________________ Познакомлюсь с привлекательной Ростовчанкой для совместного изучения Java |
|
|
|
 |
plazman : 43 Новичок
|
Фев 18, 2012 12:48 |
|
|
| Цитата: |
| Так что вместо написания собственной ORM читайте документацию в ней всё написано |
Так там между строк чёрным по белому так и написано...
В Hibernate нельзя простым способом типа
| Код: |
| EntityManager.select(Partner.class, "+code, name, type.* -type.description") |
выполнить загрузку списка объектов по определённым полям.
для решения этой задачи мучайтесь с помощью феч методов типа
| Код: |
List<Single> findSingleByCriteria(SingleSearchCriteria singleCriteria) {
Criteria criteria = session.createCriteria(Single.class);
if (singleCriteria.joinArtist()) {
criteria.setFetchMode("artist", FetchMode.JOIN)
}
if (singleCriteria.joinAlbum()) {
criteria.setFetchMode("album", FetchMode.JOIN)
}
if (singleCriteria.getTitlePattern() != null) {
criteria.addRestrictions(Restirctions.ilike("title"), singleCriteria.getTitlePattern())
}
... настройка других параметров запроса
return criteria.list();
}
|
Действительно... зачем на всё упрощать...надо что бы всё было сложно и запутанно...при 10-ти вариантах загрузки нам всего лишь нужно 10 раз использовать условие if ()...
За любовь к Hibernate надо платить....
| Цитата: |
| Как человек уже написавший свою ORM |
Ну темплейт метод и полноценный ORM это немножко разные вещи... |
|
|
|
 |
Vermut : 1063 Завсегдатай Откуда: Ростов-на-Дону
|
Фев 18, 2012 13:12 |
|
|
| plazman писал(а): |
В Hibernate нельзя простым способом типа
| Код: |
| EntityManager.select(Partner.class, "+code, name, type.* -type.description") |
|
Получается тот же самый HQL, плюсики минусики и звездочки не стоят того чтобы ради сокращения на несколько символов писать свою ORM. У тебя еще выходит что запрос статический, попробуй сформировать что-то сложное в зависимости от условий и быстро поймешь что склейка строк не вариант и Criteria API выглядит получше. _________________ Познакомлюсь с привлекательной Ростовчанкой для совместного изучения Java |
|
|
|
 |
|
|
|