Конвертировать список Hibernate без его инициализации - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть две сущности: колода и карта

@Entity
class Deck {
    private String name;

    @ManyToMany
    private List<Card> cards;
}

@Entity
class Card {
    private String name;

    @ManyToMany
    private List<Deck> decks;
}

И у меня есть Модель для каждой сущности

class DeckModel {
    private String name;
    private List<CardModel> cards;
}

class CardModel {
    private String name;
    private List<DeckModel> decks;
}

Теперь я хочу преобразовать Deck в DeckModel, поэтому я создал следующие две функции:

DeckModel convert(Deck deck) {
    DeckModel model = new DeckModel();
    model.setName(deck.getName());
    model.setCards(deck.getCards().stream()
            .map(card -> convert(card))
            .collect(Collectors.toList()));
    return model;
}

CardModel convert(Card card) {
    CardModel model = new CardModel();
    model.setName(card.getName());
    model.setDecks(deck.getDecks().stream()
            .map(deck -> convert(deck))
            .collect(Collectors.toList()));
    return model;
}

Проблема с этим фрагментом кода заключается в том, что когда я конвертирую Card(s) в CardModel(s), я запускаю ленивую загрузку всех карт, связанных с колодами, которые я конвертирую, но я хочу решить это позже в моем приложении. если я хочу или не получить все Card(s), связанные с Deck.

Есть ли простой / стандартный способ сделать это?

Ответы [ 3 ]

0 голосов
/ 14 сентября 2018

Можно заранее проверить, инициализирована ли отложенная коллекция Hibernate с помощью метода:

Hibernate.isInitialized

пример:

CardModel convert(Card card) {
    CardModel model = new CardModel();
    if (Hibernate.isInitialized(deck.getDecks())) {
         model.setName(card.getName());
         model.setDecks(deck.getDecks().stream()
            .map(deck -> convert(deck))
            .collect(Collectors.toList()));
    }
    return model;
}

Используя его, вы можете проверить его состояние и, если он не инициализирован, просто вернуть пустой список.

0 голосов
/ 18 сентября 2018

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

Я создал объект LazyList, для которого требуется ListInitializer, при первой операции LazyList вызовет ListInitializer, который вернет List, LazyList затем делегирует все операции List, возвращенному из ListInitializer.В моем конкретном случае ListInitializer преобразует и возвращает преобразованный List.Таким образом, мой List не будет преобразован, если LazyList никогда не будет использоваться.

public class LazyList<T> implements List<T> {

    private final ListInitializerSingleton<T> singleton;

    public LazyList(ListInitializer<T> initializer) {
        this.singleton = new ListInitializerSingleton<>(initializer);
    }

    @Override
    public int size() {
        return singleton.list().size();
    }

    @Override
    public boolean isEmpty() {
        return singleton.list().isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return singleton.list().contains(o);
    }

    @NotNull
    @Override
    public Iterator<T> iterator() {
        return singleton.list().iterator();
    }

    @NotNull
    @Override
    public Object[] toArray() {
        return singleton.list().toArray();
    }

    @NotNull
    @Override
    public <T1> T1[] toArray(@NotNull T1[] a) {
        return singleton.list().toArray(a);
    }

    @Override
    public boolean add(T t) {
        return singleton.list().add(t);
    }

    @Override
    public boolean remove(Object o) {
        return singleton.list().remove(o);
    }

    @Override
    public boolean containsAll(@NotNull Collection<?> c) {
        return singleton.list().containsAll(c);
    }

    @Override
    public boolean addAll(@NotNull Collection<? extends T> c) {
        return singleton.list().addAll(c);
    }

    @Override
    public boolean addAll(int index, @NotNull Collection<? extends T> c) {
        return singleton.list().addAll(index, c);
    }

    @Override
    public boolean removeAll(@NotNull Collection<?> c) {
        return singleton.list().removeAll(c);
    }

    @Override
    public boolean retainAll(@NotNull Collection<?> c) {
        return singleton.list().retainAll(c);
    }

    @Override
    public void clear() {
        singleton.list().clear();
    }

    @Override
    public T get(int index) {
        return singleton.list().get(index);
    }

    @Override
    public T set(int index, T element) {
        return singleton.list().set(index, element);
    }

    @Override
    public void add(int index, T element) {
        singleton.list().add(index, element);
    }

    @Override
    public T remove(int index) {
        return singleton.list().remove(index);
    }

    @Override
    public int indexOf(Object o) {
        return singleton.list().indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        return singleton.list().lastIndexOf(o);
    }

    @NotNull
    @Override
    public ListIterator<T> listIterator() {
        return singleton.list().listIterator();
    }

    @NotNull
    @Override
    public ListIterator<T> listIterator(int index) {
        return singleton.list().listIterator(index);
    }

    @NotNull
    @Override
    public List<T> subList(int fromIndex, int toIndex) {
        return singleton.list().subList(fromIndex, toIndex);
    }

    @FunctionalInterface
    public interface ListInitializer<T> {
        List<T> initialize();
    }

    private class ListInitializerSingleton<T> {

        private final ListInitializer<T> initializer;

        private List<T> list;

        ListInitializerSingleton(ListInitializer<T> initializer) {
            this.initializer = initializer;
        }

        List<T> list() {
            if (list == null) {
                list = initializer.initialize();
            }
            return list;
        }
    }
}

Использование:

DeckModel convert(Deck deck) {
    DeckModel model = new DeckModel();
    model.setName(deck.getName());
    LazyList<CardModel> cards = new LazyList<>(() -> {
        deck.getCards().stream()
                .map(card -> convert(card))
                .collect(Collectors.toList());
    })
    model.setCards(cards);
    return model;
}

CardModel convert(Card card) {
    CardModel model = new CardModel();
    model.setName(card.getName());
    LazyList<DeckModel> decks = new LazyList<>(() -> {
        card.getDecks().stream()
                .map(deck -> convert(deck))
                .collect(Collectors.toList());
    })
    model.setDecks(deks);
    return model;
}
0 голосов
/ 14 сентября 2018

Вам нужно повторить цикл for и установить его вручную, так как модели в списке различаются.Вы не можете использовать Отражение , поскольку поля моделей различаются.иначе вы можете использовать BeanUtils.copyProperties (), чтобы отобразить поля DeckEntity в Deck и установить этот объект Deck в вашем списке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...