Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > JPA, Hibernate, persistence, FetchType


Автор: LLIbIcpEP 20.10.2010, 13:31
Доброго времени суток. Есть такое дело:
Код

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Unit {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @NotNull(message = "id is required")
    @Column(nullable = false, unique=true)
    private Long id;

Код

@Entity
public class MessageDependency extends Unit {
    
    @ManyToOne(fetch=FetchType.LAZY)
    @NotNull(message = "Owner is required")
    private UserInstance owner;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @NotNull(message = "Dependency is required")
    private Unit dependency;

Код

@Entity
public class UserInstance extends Unit {
    
    @NotNull(message = "uid is required")
    @Column(nullable = false, unique=true)
    @Min(1)
    private Long uid;

Древо наследования достаточно большое, UserInstance - прямой наследник Unit, поле dependency может содержать все что угодно, унаследованное от Unit. Делаю примерно так:
Код

UserInstance userInstance = entityManager.createQuery(
    "select u from UserInstance u where u.uid = :p0", UserInstance.class)
        .setParameter("p0", 1l).getSingleResult();
mess = entityManager.createQuery(
    "select m from MessageDependency m fetch all properties where m.owner = :p0",
        MessageDependency.class).setParameter("p0", userInstance).getResultList();

Потом сериализую полученный лист в JSON через XStream. Вообщем в итоге у меня поле dependency сериализуется как прокси, не смотря на "fetch all properties" в HQL. Почему "fetch all properties" игнорируется? Пробовал Hibernate.initialize(), пробовал @Fetch(FetchMode.SELECT). Не помогает. Поле owner сериализуется нормально, но только за счет того, что я его явно запросил перед этим. Делать так для dependency не получится - там может быть все, что угодно, и заранее я не знаю, какие там могут быть поля.
Помогите, пожалуйста. Заранее благодарен.

Автор: LLIbIcpEP 23.10.2010, 11:46
Пока решил проблему такими костылями:
Код
    public static <T extends Unit> T loadUnitFields(T unit) throws ApiException {
        Hibernate.initialize(unit);
        Class<? extends Unit> clasz = unit.getClass();
        while (true) {
            Field[] tmp = clasz.getDeclaredFields();
            for (Field field : tmp) {
                try {
                    if (Unit.class.isAssignableFrom(field.getType())) {
                        field.setAccessible(true);
                        Unit thisUnit = (Unit) field.get(unit);
                        if (thisUnit != null) {
                            thisUnit = DataRepositoryProducer.findUnit(Unit.class, thisUnit.getId());
                            field.set(unit, loadUnitFields(thisUnit));
                        }
                    }
                } catch (Exception e) {
                    throw new ApiException(e);
                }
            }
            if (clasz.equals(Unit.class)) {
                break;
            } else {
                clasz = (Class<? extends Unit>) clasz.getSuperclass();
            }
        }
        return unit;
    }

Это конечно костыли, при том не самые изящные.
Все таки интересно, почему игнорируется "fetch all properties". Ведь в документации написано, что это как-раз и служит для моей цели. Или оно опять-же не работает рекурсивно? Не грузит поля полей? Но я не вижу разницы в возвращаемых данных без и с "fetch all properties".
Очень хочется решить проблему правильно, средствами хибера. Но если что, укажите хотя-бы на ошибки в костылях...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)