【发布时间】:2012-02-19 16:16:38
【问题描述】:
我将 Spring 和 Hibernate 与注释驱动的事务一起使用。
运行我的应用程序时,我收到一个异常“createCriteria is not valid without active transaction”。根据这个Spring/Hibernate Exception: createCriteria is not valid without active transaction,解决方案是从sessionFactory配置中删除<property name="current_session_context_class">thread</property>这一行。
但是,我还需要在 @PostConstruct 方法中做一些事务性工作(从 DB 初始化)。 @PostConstruct 方法不能是事务性的,所以我打开了一个手动事务 - 但是当我删除上面的行时这不起作用(得到一个异常 org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here)。根据几个消息来源,解决方案是将<property name="current_session_context_class">thread</property> 添加到配置中......
这是我的代码(我知道它不太干净 - 我一直在摆弄它以了解问题所在):
`@Transactional 公共类 TaskControllerImpl 实现 TaskController {
@Autowired
TaskDAO taskDAO;
@Autowired
MethodDAO methodDAO;
@Autowired
SessionFactory sessionFactory;
ExecutorService threadPool = Executors.newCachedThreadPool();
/**
* Map of method name to TaskExecutor for all defined methods
*/
private Map<String, TaskExecutor> executorsByMethod;
final Logger logger = LoggerFactory.getLogger(TaskControllerImpl.class);
/**
* Initializes the mapping of method name to TaskExecutor
*/
@PostConstruct
public void init() {
// @Transactional has no effect in @Postconstruct methods so must do this manually
Transaction t = sessionFactory.getCurrentSession().beginTransaction();
executorsByMethod = new HashMap<String, TaskExecutor>();
List<Method> methods = methodDAO.findAll();
for (Method method : methods) {
if (method.getExecutorClassName() != null) {
try {
TaskExecutor executor = createTaskExecutor(method);
executorsByMethod.put(method.getName(), executor);
} catch (Throwable e) {
logger.error("Coud not create/instantiate executor " + method.getExecutorClassName());
e.printStackTrace();
}
}
}
t.commit();
}
@Override
public void run() {
Collection<Task> tasksToExecute = fetchTasksToExecute();
for (Task task : tasksToExecute) {
String method = task.getMethod().getName();
executorsByMethod.get(method).addTask(task);
}
}
/**
* Fetches all tasks which need to be executed at the current time
*
* @return
*/
private Collection<Task> fetchTasksToExecute() {
try {
Search search = new Search();
search.addFilterLessThan("actionDate", DateUtil.now());
search.addFilterEqual("status", TaskStatus.PENDING.getCode());
search.addSort("actionDate", false);
return taskDAO.search(search);
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
`
配置:
`
<!-- Configure a JDBC datasource for Hibernate to connect with -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${connection.url}" />
<property name="username" value="${connection.username}" />
<property name="password" value="${connection.password}" />
</bean>
<!-- Configure a Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.grroo.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<!-- prop key="hibernate.current_session_context_class">thread</prop-->
<prop key="hibernate.connection.zeroDateTimeBehavior">convertToNull</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven/>
`
所以我在这里有点关于如何使 init() 和 run() 工作的问题 22。有什么想法吗?
【问题讨论】:
-
你应该使用 TransactionTemplate 见stackoverflow.com/questions/17346679/…
标签: hibernate spring transactions