2015-02-11 5 views
0

Я знаю, что это далеко не новый вопрос. Например, множество рецептов можно найти here как в вопросе, так и в ответах. Однако мне не удалось решить мою проблему.Hibernate 4 Не удалось получить синхронизацию по транзакции Сессия для текущей темы

I пользователь Hibernate 4 + Spring 4 и PostgreSQL. У меня DAO и DAOImpl отмечены @Transactional для всего класса:

package org.app.server.dao.impl; 

@Repository 
@Transactional 
public class UserDAOImpl implements UserDAO { 

    @Autowired 
    private SessionFactory sessionFactory; 

    public User getUser(String login) { 
    User user = 
      (User) sessionFactory.getCurrentSession().createQuery("from User p where p.login=:login") 
        .setParameter("login", login).uniqueResult(); 
    return user; 
    } 

    @Override 
    public void addUser(User user) { 
    sessionFactory.getCurrentSession().save(user); 
    } 
} 

Пользователь является @Entity:

package org.app.model; 

@Entity 
@Table(name = "person") 
public class User implements Serializable { 
    private static final long serialVersionUID = 1L; 

    public User() { 
    } 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(columnDefinition = "serial") 
    private Integer id; 

    @NotNull 
    private String login; 

    @NotNull 
    private String password; 

    private String email; 

// getters and setters 
} 

Теперь я подпишусь Пользователя из-й формы. Контроллер ловит данные:

package org.app.controller; 

@Controller 
@Scope("prototype") 
public class MyController { 

@Autowired 
private UserOperations userOperations; 

    @ModelAttribute("user") 
    public User getUserObject() { 
    return new User(); 
    } 

    @RequestMapping(value="/newuser", method = RequestMethod.POST) 
    public ModelAndView newUser(@ModelAttribute("user") User user, BindingResult result) { 
    userOperations.signup(user); 
    return new ModelAndView("redirect:/somepage"); 
    } 
} 

И посылает его UserOperations @Component для того, чтобы проверить, если такой Логин уже существует и вставить новый пользователь. Очевидно, что должно быть сделано в одной транзакции:

package org.app.server; 

@Component 
@Scope("prototype") 
public class UserOperations { 

    @Autowired 
    private UserDAO userDAO; 

    @Transactional 
    public void signup(User user) { 
    if (userDAO.getUser(user.getLogin()) == null) { 
     userDAO.addUser(user); 
    }  
    } 
} 

Так я бегу Когда N это, у меня есть следующие:

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread 
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134) 
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014) 
    at org.app.server.dao.impl.UserDAOImpl.getUser(UserDAOImpl.java:30) 
    at org.app.server.UserOperations.signup(UserOperations.java:25) 
    at org.app.controller.StartPageController.newUser(StartPageController.java:56) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 

Вот мои XML конфиги: applicationContext.xml

<context:component-scan base-package="org.app.server" /> 
<context:annotation-config /> 

<tx:annotation-driven transaction-manager="transactionManager" /> 
<bean id="transactionManager" 
    class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

<bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource" 
    p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.databaseurl}" 
    p:username="${jdbc.username}" p:password="${jdbc.password}" /> 

<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate"> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

<bean id="sessionFactory" 
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" depends-on="flyway"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="packagesToScan"> 
     <array> 
       <value>org.app.server</value> 
       <value>org.app.model</value> 
     </array> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.show_sql">true</prop> 
      <prop key="hibernate.dialect">${jdbc.dialect}</prop> 
      <prop key="hibernate.connection.charSet">UTF-8</prop> 
      <prop key="hibernate.hbm2ddl.auto">${jdbc.hbm2ddl}</prop> 
     </props> 
    </property> 
</bean> 

И SpringMVC-servlet.xml:

<context:component-scan base-package="org.app.controller, org.app.server" /> 
<mvc:annotation-driven /> 
<mvc:default-servlet-handler /> 

Еще одна интересная вещь в том, что, когда я использую GetUser и AddUser (регистрация) отдельно, непосредственно от контроллера, к примеру, он отлично работает.

+0

Вы '@ Autowiring' в' UserOperation' в 'StartPageController'? Spring не обертывает «UserOperation» с помощью AOP black majick для управления транзакциями. Либо '' пост-процессор не собирает его, либо вы не получаете экземпляр объекта из контекста Spring. –

+0

Да, я знаю. Я понимаю. Я обновил вопрос. – bdshadow

+0

Возможно, это связано с тем, что управление транзакциями осуществляется только в контексте приложения, а не в контексте сервлета. Возможно, вы можете попробовать добавить пакет 'org.app.controller' в' applicationContext.xml' в тег ''. Не уверен, у меня нет большого опыта работы с Spring, и это настройка XML, но я думаю, что стоит попробовать. –

ответ

0

Вы должны openSession до вашего звонка

User user = (User)sessionFactory.getCurrentSession().createQuery("from User p where p.login=:login").setParameter("login", login).uniqueResult(); 

Так что вы должны сделать:

Session session = sessionFactory.openSession(); 
User user = (User) session.createQuery("from User p where p.login=:login").setParameter("login", login).uniqueResult(); 
Смежные вопросы

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