2015-01-06 1 views
0

Я работаю над приложением Spring-MVC, в котором я использую Hibernate в качестве инструмента ORM. Я добавляю функции чата в приложение, и когда я пытаюсь добавить сообщение чата, я получаю Ошибка сеанса Hibernate No. Я проверил различные решения в сети, и они предлагают использовать метод Eager, но у меня уже есть его как загружаемая загрузка, и все же я получаю ошибку. Я отправляю код, любезно посмотрю.Hibernate не может инициализировать прокси - нет сеанса даже с загрузкой Eager

Модель пользователя:

@Entity 
@Table(name="userinfo") 
public class User implements UserDetails{ 

// I am using 2 foreign keys in the database to store the sender and receiver id for the message. 

    @OneToMany(mappedBy = "user2", fetch = FetchType.EAGER) 
    private Set<Messages> messages1 = new HashSet<Messages>(); 

    @OneToMany(mappedBy = "user3", fetch = FetchType.EAGER) 
    private Set<Messages> messages2 = new HashSet<Messages>(); 
} 

Сообщения Модель:

@Entity 
@Table(name = "conversation") 
public class Messages { 
@ManyToOne 
    @JoinColumn(name = "id") 
    private User user2; 

    @ManyToOne 
    @JoinColumn(name = "userinfo_id") 
    private User user3; 
} 

MessagesDAOImpl:

@Override 
    @Transactional 
    public boolean addMessage(User sender, User receiver, Messages messages) { 

    @M.Denium : When I remove the below 4 lines, it works. Can you please tell me why? 
      session = this.sessionFactory.getCurrentSession(); 

/* int id = sender.getId(); 
    int id2 = receiver.getId(); 
    User sender1 = (User) session.get(User.class,id); 
    User receiver1 = (User) session.get(User.class,id2);*/ 
    /* sender.getMessages1().add(messages); 
    receiver.getMessages2().add(messages);*/ 
    messages.setConversationtimestamp(new Date()); 
    messages.setUser2(sender); 
    messages.setUser3(receiver); 
    session.merge(messages); 
    session.flush(); 
    return true; 
} 
@Override 
    @Transactional 
    public List<Messages> listMessagesForUser(User user) { 
     session = this.sessionFactory.openSession(); 
     /* if(session == null){ 
      session = this.sessionFactory.openSession(); 
     } else{ 
      session = this.sessionFactory.getCurrentSession(); 
     }*/ 
     int id = user.getId(); 
     Query query = session.createQuery("from Messages as m where m.user2.id=:id"); 
     query.setParameter("id",id); 
     List<Messages> messagesList= query.list(); 
     session.flush(); 
     return messagesList; 
    } 

MessageController:

@Controller 
public class MessageController { 

@RequestMapping(value = "/messages/add/{receiverid}") 
    public String sendMessages(@ModelAttribute("messages")Messages messages, @PathVariable("receiverid") int receiverid, Model model){ 
     User user = userService.getCurrentlyAuthenticatedUser(); 
     User user1 = userService.getUserById(receiverid); 
     this.messageService.addMessage(user,user1,messages); 
     model.addAttribute("messages", new Messages()); 
     model.addAttribute("listMessages", this.messageService.listMessagesForUser(user)); 
     return "messages"; 
    } 

    @RequestMapping(value = "/messages/list") 
    public String listMessages(@ModelAttribute("messages") Messages messages, Model model){ 
     User user = userService.getCurrentlyAuthenticatedUser(); 
     model.addAttribute("messages", new Messages()); 
     model.addAttribute("listMessages", this.messageService.listMessagesForUser(user)); 
     return "messages"; 
    } 
} 

Что я делаю не так, любые указатели приветствуются, если есть больше информации требуется, любезно дайте мне знать. Спасибо.

+0

Не используйте 'openSession' для получения сеанса, всегда используйте' getCurrentSession', иначе вы открываете неуправляемые сеансы. Проблема заключается в том, что вы извлекаете «Пользователь», а затем передаете его. Сеанс, который использовался для извлечения пользователя, уже закрыт. Вы должны переместить эту логику в один метод, который является '@ Transactional', теперь у вас есть бизнес-логика в вашем контроллере. –

+0

@ M.Deinum Спасибо, мне удалось решить проблему, удалив код из MessagesDAOImpl и работая над уже существующими сущностями в сеансе. У меня только один вопрос: какая бизнес-логика я имею прямо сейчас в контроллере? –

+0

Извлечение пользователей должно, imho, быть частью вашего метода обслуживания (который вы также делаете), а не в вашем контроллере. Это также облегчило бы тестирование (и, скорее всего, сэкономило бы вам ответы на вопросы) :). –

ответ

1

Добавив @Transactional в свои методы, весна позаботится о создании/закрытии сеанса спящего режима и создании/фиксации/откате транзакций.
Так удалить этот код в "addMessage()" метод

if(session == null) { 
    session = this.sessionFactory.openSession(); 
}else { 
    session = this.sessionFactory.getCurrentSession(); 
} 

и удалить эту строку в "listMessagesForUser()" метод

session = this.sessionFactory.openSession(); 

Вместо просто получить текущую сессию с «sessionFactory.getCurrentSession() "и использовать его в рамках метода. Также вам необходимо включить управление транзакциями, добавив @EnableTransactionManagement на ваш компонент @Configuration.

Вы можете прочитать все о spring transaction management.

+0

Я пробовал, что вы сказали, я получаю NullPointerExceptions. Вы хотите, чтобы я опубликовал любой код для вас, счастлив сделать это и учиться. Большое спасибо. –

+0

В "listMessagesForUser" используйте getCurrentSession() вместо openSession() – outdev

+0

Хорошо, я сделал это, я удалил весь код, мой плохой. Благодарю. –

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