2015-09-05 3 views
2

У меня есть проблема с транзакцией в Spring MVC. У меня есть 2 объекта (User, Role) в ManyToMany. У меня есть сервис, где я хочу, чтобы получить Роли пользователя:Транзакция не работает во многих многих

public Set<Role> getUserRoles(long id) { 
    Set<Role> roles = userRepository.findById(id).getRoles(); 
    return roles; 
} 

Мой класс Пользователь:

@ManyToMany(fetch = FetchType.LAZY) 
@JoinTable(name = "USER_ROLE", joinColumns = { 
     @JoinColumn(name = "ID_USER", referencedColumnName = "ID_USER") }, inverseJoinColumns = { 
       @JoinColumn(name = "ID_ROLE", referencedColumnName = "ID_ROLE") }) 
public Set<Role> getRoles() { 
    return roles; 
} 

Когда я использую это в моем контроллере:

Set<Role> roles=userService.getUserRoles(1); 
    for (Role r : roles) { 
     System.out.println(r.getName()); 
    } 

я получил LazyInitializationException. Сервис обозначен как @ Трансакция и метод

TransactionSynchronizationManager.isActualTransactionActive() 

в сервисе метод возвращает true.

public Set<Role> getUserRoles(long id) { 
    Set<Role> roles = userRepository.findById(id).getRoles(); 
    for (Role r : roles) { 
     System.out.println(r.getName()); 
    } 
    return roles; 
} 

Я заметил, что когда я печатаю роли в обслуживании, мой контроллер работает. Спасибо за любую помощь

EDIT

В контроллере у меня есть код:

for (Role r : roles) { 
     System.out.println(r.getName()); 
    } 

Когда мой метод обслуживание:

public Set<Role> getUserRoles(long id) { 
    Set<Role> roles = userRepository.findById(id).getRoles(); 
    return roles; 
} 

затем System.out.println (UserService .getUserRoles (1)); в контроллере бросок LazyInitializationException но когда мой метод обслуживания:

public Set<Role> getUserRoles(long id) { 
    Set<Role> roles = userRepository.findById(id).getRoles(); 
    for (Role r : roles) { 
     System.out.println(r.getName()); 
    } 
    return roles; 
} 

затем System.out.println (userService.getUserRoles (1)); в контрольных работах

+0

вы объясняете, когда это работает, но не тогда, когда оно не работает, а также не то, что «не работает» означает, в частности (что происходит, что должно произойти, журналы ошибок) – hoijui

+0

i обновил мое сообщение – cinek181992

ответ

1

@ cinek181992, как вы заметили, когда System.out.println выполняется в сервисе, он работает, и это связано с тем, что вы находитесь в транзакции, поэтому отношения с сущностью ролей, которые не нужны, могут быть извлечены и распечатаны. Посмотрите, что когда он пытается прочитать атрибут, он загружает данные атрибута, чтобы его можно было прочитать в следующий раз в контроллере.
Это связано с тем, что он не работает в контроллере, поскольку транзакция закончилась, когда служба вернулась, и System.out.println по полученным данным пытается прочитать атрибуты сущностей, которые не были загружены в транзакцию.

Есть несколько вариантов решения вашей проблемы.
Если отношения @ManyToOne должны быть прочитаны (как правило,), отметьте их как EAGER.

Несколько раз, и я предпочитаю, лучше не работать с сущностями из служебного уровня и отправлять только DTO на веб-слой.

+0

Есть ли у вас хорошие примеры этого метода? – cinek181992

+0

ОК, но стратегия сохранения всегда зависит от ваших потребностей. Можете ли вы опубликовать Role.java? Это то, что вызывает вашу проблему. А также то, что вам нужно именно от роли на уровне обзора? – AlexCG

1

@Transactional, вероятно, только вокруг вашего userService. Это означает, что при выходе из метода транзакция будет совершена.

Позже, на вашем контроллере, вы пытаетесь получить ленивое свойство объекта (роли пользователя). Поскольку вы больше не совершаете транзакции, вы получаете LazyInitializationException.

Если вы хотите получить роли, отметьте контроллер как @Transactional или получите роли eagerly.

+0

, так что если я хочу чтобы получить роли пользователя, я должен использовать @Transactional или запрос, чтобы найти его? Я подозреваю, что запрос - лучший выбор. – cinek181992

Смежные вопросы