У меня проблемы с прокси-объектами в Грайле. Если предположить, что у меня есть следующийGrails. Hibernate ленивый погрузка нескольких объектов
class Order {
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name="xxx", joinColumns = {@JoinColumn(name = "xxx")}, inverseJoinColumns = {@JoinColumn(name = "yyy")})
@OrderBy("id")
@Fetch(FetchMode.SUBSELECT)
private List<OrderItem> items;
}
class Customer {
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true)
@JoinColumn(name = "xxx",insertable = false, nullable = false)
private OrderItem lastItem;
private Long lastOrderId;
}
И внутри некоторого класса контроллера
//this all happens during one hibernate session.
def currentCustomer = Customer.findById(id)
//at this point currentCustomer.lastItem is a javassist proxy
def lastOrder = Order.findById(current.lastOrderId)
//lastOrder.items is a proxy
//Some sample actions to initialise collections
lastOrder.items.each { println "${it.id}"}
После итерации lastOrder.items
все еще содержит прокси-сервер currentCustomer.lastItem
. Например, если есть 4 элементы коллекции lastOrder.items, это выглядит следующим образом:
- объект
- объект
- Javassist прокси (все поля равны нулю, включая идентификатор поля). Это тот же объект, что и в currentCustomer.lastItem.
- объект
Кроме того, этот прокси-объект имеет все свойства, установленные в нулевое значение, и это не инициализируется, когда добытчики вызываются. Мне нужно вручную вызвать GrailsHibernateUtils.unwrapIdProxy()
на каждый элемент внутри lastOrder.items
, чтобы убедиться, что внутри нет прокси-серверов (что в основном приводит к извлечению EAGER).
Этот один прокси-объект приводит к некоторым действительно странным Исключениям, которые трудно отследить на этапе тестирования.
Интересный факт: если я изменяю порядок операций (сначала загружаем заказ и второй клиент), каждый элемент внутри lastOrder.items
инициализируется.
Вопрос: Есть ли способ сообщить Hibernate, что он должен инициализировать коллекции, когда они касаются, независимо от того, какие элементы из коллекции уже проксированы в сеансе?
Если 'является Оно деталь A.' прокси затем 'Println«$ {it.id } "' не инициирует инициализацию, для этого вам нужно получить свойство non-ID. –
@IanRoberts Любая ссылка на официальную документацию? Причина с моей точки зрения для прокси-объекта действительно имеет смысл инициализировать поле Id. Особенно в тех случаях, когда используется ManyToOne (внешний ключ хранится в родительском объекте) – WeMakeSoftware
Прокси-сервер в Hibernate является держателем, который знает ID, но ничего больше. Он может отвечать на запросы, чтобы получить идентификатор, не заходя в базу данных, но когда вы просите его о чем-либо еще, он использует идентификатор (который он уже знает) для запроса базы данных и загрузки реального объекта со всеми его свойствами. Последующий метод вызывает делегирование прокси-сервера непосредственно базовому объекту. –