Я знаю, что это далеко не новый вопрос. Например, множество рецептов можно найти 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 (регистрация) отдельно, непосредственно от контроллера, к примеру, он отлично работает.
Вы '@ Autowiring' в' UserOperation' в 'StartPageController'? Spring не обертывает «UserOperation» с помощью AOP black majick для управления транзакциями. Либо ' ' пост-процессор не собирает его, либо вы не получаете экземпляр объекта из контекста Spring. –
Да, я знаю. Я понимаю. Я обновил вопрос. – bdshadow
Возможно, это связано с тем, что управление транзакциями осуществляется только в контексте приложения, а не в контексте сервлета. Возможно, вы можете попробовать добавить пакет 'org.app.controller' в' applicationContext.xml' в тег ' '. Не уверен, у меня нет большого опыта работы с Spring, и это настройка XML, но я думаю, что стоит попробовать. –