В моем веб-приложении я загружаю много сущностей, чтобы отобразить их в виде таблицы. Я могу щелкнуть по каждой табличке, чтобы получить «подробную информацию» о конкретной организации.
Для меня было очевидным не загружать «подробную информацию» для просмотра таблицы, а только тогда, когда кто-то хочет ее увидеть (щелкает строку).
Просто установка (fetch = FetchType.LAZY)
для этих полей не сработала, потому что объекты извлекаются после выборки, и в моем WebApp будут нулевые значения.
Хорошо, следующее, что я сделал, это предотвратил отсоединение, поместив мои операции извлечения в StatefulSessionBean с расширенным PersistenceContext.
@PersistenceContext(unitName="unitname", type=PersistenceContextType.EXTENDED)
private EntityManager em;
Это работает, но также вызывает странные побочные эффекты (особенно ConcurrentAccessExceptions
при некоторых перезагрузках страницы, которые я мог бы исправить, установив некоторые свойства openjpa)
Сервлеты нуждаются в собственных загружающих ejbs, так как они не объединяются с SFSB. Кажется, в большинстве случаев все работает нормально, но я ожидаю, что s ** t скоро поразит вентилятор.
У меня вопрос, не ошибся ли я. Все это кажется мне немного неловким. Использование bean-компонента с состоянием, когда нет реального разговора и пользователь может уйти в любое время, не вызывая какой-либо метод @ Remove-Method. Необходимость закрыть ресурсы по тайм-ауту, когда пользователь давно ушел, что приводит к множеству открытых неиспользуемых SFSB.
LazyLoading - это довольно простая вещь, но в среде Java EE я не понимаю, как это сделать. Какова лучшая практика?
Спасибо.
UPDATE
теперь я вручную получаю поля
@SuppressWarnings("unchecked")
public <T extends BasicEntity> T loadLazyField(T entity, String field) throws NoSuchFieldException {
if (!typeHasField(entity.getClass(), field)) {
throw new NoSuchFieldException(entity.getClass().getSimpleName() + " has no field called " + field);
}
String queryString = String.format("SELECT x FROM %s x WHERE x = :entity LEFT JOIN FETCH x.%s", entity.getClass()
.getSimpleName(), entity, field);
Query q = em.createQuery(queryString);
q.setParameter("entity", entity);
return (T) q.getSingleResult();
}
@SuppressWarnings("unchecked")
public <T extends BasicEntity> T loadLazyFields(T entity, String[] fields) throws NoSuchFieldException {
String queryString = String.format("SELECT x FROM %s x WHERE x = :entity", entity.getClass().getSimpleName());
for (String field : fields) {
if (!typeHasField(entity.getClass(), field)) {
throw new NoSuchFieldException(entity.getClass().getSimpleName() + " has no field called " + field);
}
queryString += String.format(" LEFT JOIN FETCH x.%s", field);
}
Query q = em.createQuery(queryString);
q.setParameter("entity", entity);
return (T) q.getSingleResult();
}
private boolean typeHasField(Class<?> type, String field) {
try {
type.getDeclaredField(field);
return true;
} catch (NoSuchFieldException e) {
return false;
}
}