2016-03-17 2 views
8

Я разрабатываю относительно большой проект с использованием Spring Boot, и в общем, я очень доволен этим, но у меня возникают некоторые проблемы, которые на мой взгляд, это не проблема.Lazy One-To-One Spring JPA и здание «динамический» JSON

  1. Прежде всего, взаимно-однозначное отношение. Это расстраивает то, что это не работает, как должно (по крайней мере, на мой взгляд).

    У меня есть два объекта, User и UserProfile, например. У них есть отношения «один-к-одному», но большую часть времени мне нужны только данные User, но он выбирает (независимо от того, что я пытаюсь, и о, мальчик, я пробовал предложения мира на каждое сообщение для 5 страниц Google).

    Итак, есть мой первый вопрос, есть ли способ получить ленивые отношения «один-к-одному» в JPA и Spring? (Потому что большинство сообщений старше 2-3 лет).

  2. Другая проблема, с которой я столкнулся, заключается в том, чтобы построить ответ JSON «динамическим» способом. Я сделал некоторые вещи, используя Rails, и был очень доволен JBuilder или даже to_json, который дал мне возможность построить ответ json в зависимости от контроллера и моих потребностей на данный момент.

    Весной я увидел следующие решения:

    • Jackson @JsonView (который не решает полностью мою проблему, потому что ответы не то, что статические и атрибут не может быть назначено несколько представлений (насколько Я понял эту концепцию));
    • установка нулевых атрибутов, которые я не хочу откликать (используя это, но я слишком уродлив и похож на неправильное пошаговое руководство);
    • или здание HashMap как я построю .json.jbuilder на Rails (но это убивает мое исполнение, так как иногда у него есть отношения, поэтому много for для создания json, а также это выглядит как уродливое пошаговое руководство).

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

EDIT 1

Уже пытался добавить optional = false на @OneToOne аннотации решить нетерпеливые нагрузки OneToOne отношений, как @snovelli предложил. Пример:

@OneToOne(optional=false, fetch = FetchType.LAZY) 
public UserProfile getUserProfile(){ ... } 
+0

Ваш вопрос содержит два несвязанных вопроса. Вы должны выбрать один и извлечь другой в отдельный вопрос. Во всяком случае, это первый вопрос SO, в котором я добавил два ответа. :) –

+0

Я подумал об этом, но у меня были некоторые вопросы, подобные этим, но никто не ответил, поэтому я разместил это, зная, что мне нужно будет поставить щедрость, чтобы на него можно было ответить, и поскольку у меня слишком много очков чтобы сэкономить на щедрости, я поставил их в один вопрос: (Но, по крайней мере, я думаю, что это два вопроса, которые могут быть у всех, у которых нет волшебников в Spring и JPA. – augustoccesar

ответ

6

Если столбец объединения отсутствует в таблице, в которую сопоставляется родительский элемент в взаимно однозначной ассоциации, то ассоциация cannot be lazy. Причина в том, что поставщик JPA не может определить, создавать ли прокси-сервер, чтобы он мог загрузить объект при доступе позже или оставить значение null.

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

Решения:

  1. Byte code instrumentation. Хотя широко принятый подход.
  2. Используйте один-ко-многим и введите пустой список как null, в противном случае используйте list.get(0). Вы можете, конечно, инкапсулировать это в классе сущности (getter возвращает единственный элемент списка или null). Недостатком является то, что вам придется рассматривать это как сборку в запросах JPQL.
  3. Использовать @PrimaryKeyJoinColumn вместо внешнего ключа. Если ассоциация не является необязательной (optional = false), поставщик JPA знает, что существует дочерний объект с тем же PK, поэтому он просто сохранит PK родителя как id дочернего элемента в прокси. Очевидно, что вы не можете использовать два независимых генератора id для обоих объектов, иначе PK могут быть разными. Это лучший подход, если он соответствует вашим требованиям.
  4. Также добавьте внешний ключ в родительскую таблицу (что делает отношение двунаправленным в базе данных также). Недостатком является то, что у вас теперь в основном есть две независимые ассоциации, которые вы должны поддерживать. Кроме того, существует стоимость обновления двух таблиц вместо одного (а внешние ключи должны быть нулевыми).
  5. Map родительский объект в представлении базы данных, которая соединяет родительскую таблицу с дочерней таблицы и содержит все родительские столбцы плюс идентификатор детского стола:

    @OneToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "<child id in the view>", insertable = false, updatable = false) 
    private Child child;
+0

Он отлично справился с третьим предложением. мой идентификатор типа (его высказывание, которое получает целое число, но ожидает Long), но после изменения типа, с которым он работал (это то, что я буду искать позже), важно то, что сработало. Спасибо! – augustoccesar

+0

@augustoccesar Добро пожаловать Помните, что вы не можете использовать два независимых генератора id для обоих объектов с '@ PrimaryKeyJoinColumn', связанные объекты должны иметь один и тот же PK. –

+0

Говоря тот же PK, вы имеете в виду, что на cre при этом два используют тот же инкремент, что и в случае, если 'User' имеет' id == 1', а соответствующий 'UserProfile' имеет' id == 1'? – augustoccesar

0

Что касается @OneToOne: вы обеспокоены тем более по количеству данных или нескольких запросов к БД?

В первом случае (если это возможно при использовании Spring Roo), вы можете попробовать обходное решение с отношением отношения @ManyToOne (индивидуально - это особый случай, когда много-к-одному, не так ли).

В последнем случае вы можете использовать @Embeddable для декомпозиции объекта как пользователя на несколько классов, сохраняя данные вместе в БД, поэтому для его получения будет использоваться только один запрос.

2

Что касается «динамический» JSON: Использование DTOs.

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

+0

Thats отличный образец! Не знал об этом. Я каким-то образом манипулировал ответами, но использовал HashMap. Использование DTO выглядит более корректным и удобным. Благодаря! – augustoccesar

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