Спящие ленивые поля загрузки

1

У меня проблема с спящим режимом. сценарий заключается в том, что я переделаю свой проект. мой предыдущий проект с JMS, который гладко работает с моими POJO. и теперь я пытаюсь воссоздать его с помощью Apache Mina (программирование сокетов) с помощью Google Gson.

У меня возникла проблема с ленивой загрузкой моих полей, потому что проект, который использует JMS, работает с ленивой загрузкой, но теперь я пытаюсь получить какое-то значение в базе данных, но всегда существует исключение hibernate, указывающее, что failed to lazily initialize a collection of role: class.field, no session or session was closed который я хочу загрузить лениво, я не хочу получать его каждый раз.

public class User {
    @Id
    @GeneratedValue
    @Column(name = "iduser")
    private Integer             iduser;

    @Column(name = "firstname")
    private String              firstname;

    @Column(name = "lastname")
    private String              lastname;

    //     this field causes the lazy loading exception
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    @BatchSize(size = 4)
    private Set<Transaction>    transaction;
}

и я возвращаю его в свой DAO, как это

public User findByUser(String username, String pass) {
        // TODO Auto-generated method stub
        try {
            User instance = (User) getSession().createCriteria(User.class)
                    .add(Restrictions.eq(USERNAME, username))
                    .add(Restrictions.eq(PASS, pass)).uniqueResult();
            return instance;
        } catch (RuntimeException re) {
            throw re;
        }
    }

метод, когда я вызываю службу

public ModelAndView processSignin(User currentUser, BindingResult result,
            HttpServletRequest request) {
User user = service.signin(currentUser);
//i try to convert it to GSON but when i comment this line of code it works fine. but when gson tries to convert it to json string it seems that the annotations are being executed
System.out.println(gson.toJson(user));
}

метод signin, который вызывает класс DAO

public User signinDealer(User user) {
        // TODO Auto-generated method stub
        User currentUser = userDAO.signinUser(user);
        return currentUser;
    }
Теги:
spring
hibernate

3 ответа

0
Лучший ответ

Если вы используете Spring и Hibernate (что похоже на теги вопроса), вы можете настроить управление транзакциями Spring (небольшой учебник: http://www.baeldung.com/2011/12/26/transaction- configuration-with-jpa-and-spring-3-1/).

Затем вам нужно будет аннотировать любой метод (в компоненте Spring), который использует объект Hibernate с @Transactional. Это гарантирует, что любой объект Hibernate будет загружен в контексте сеанса, и если вам случится вызвать ленивую инициализацию, Hibernate сможет извлекать объекты с помощью этого сеанса.

В вашем случае вы можете захотеть, чтобы метод, который @Transactional и сериализовал пользователя в JSON, был аннотирован с помощью @Transactional. Обратите внимание, что если у вас есть 2 контекста приложения Spring (один корень и один для Spring MVC), аннотация будет, скорее всего, работать только с компонентами, определенными в контексте корневого приложения (поэтому аннотирование контроллера может не работать, см. Методы @Transactional в @Controller класс не рассматриваются как транзакционные).

@Transactional
public String signinAndSerialize(String username, String password) {
    User user = service.signin(username, password);
    return gson.toJson(user);
}
  • 0
    отличается аннотация @Transactional от управления транзакциями с использованием AOP?
  • 0
    Нет, это, наверное, то же самое. Spring использует AOP для управления сеансом / транзакцией.
Показать ещё 3 комментария
0

По умолчанию Hibernate обеспечивает ленивую загрузку. Вы можете сделать следующее:

  1. Сначала оцените, действительно ли вам нужны данные отношений. Если вам не нужны данные отношений, есть способы/аннотации, чтобы игнорировать его во время преобразования JSON. Напр. аннотирование поля с помощью @JsonIgnore (import org.codehaus.jackson.annotate.JsonIgnore;).

  2. Если вам действительно нужны данные, тогда извлеките их, пока сеанс hibernate все еще открыт.

  3. Явно конвертируйте в EagerLoading, добавив следующий атрибут в ваш @OneToMany fetch = FetchType.EAGER. Однако это будет иметь влияние на производительность.

0

При работе с Hibernate ленивая загрузка работает только тогда, когда получатель поля вызывается внутри той же транзакции, которая загружает весь объект. Это означает, что если getter вызывается, когда транзакция завершена, а сеанс Hibernate закрыт, генерируется исключение lazy loading.

Вы можете сделать преобразование внутри блока транзакций или исключить конкретное поле из сериализации, как описано здесь

Ещё вопросы

Сообщество Overcoder
Наверх
Меню