我正在编写一个facebook应用程序。用户授权我的应用@ fb后,其着陆页将成为查看个人资料页面。虽然我提取了大量的数据,比如,喜欢,组等等。它需要很多时间才能将他重定向到登陆页面。所以我想的是,只需获取用户的电子邮件ID,教育和就业详细信息,然后将其重定向到登录页面。平均差距我在重定向之前启动了一个线程,这将从后台的帐户中提取所有数据。所以我创建了一个实现runnable的类,然后我从控制器启动了该线程。它工作正常,直到我从fb获取数据。在调用DAO的save(obj)方法时,我收到以下错误。
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
我的一位朋友建议我选择石英调度程序。所以这就是我的尝试。
FBController:
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler shed = null;
try {
shed = sf.getScheduler();
shed.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
JobDetail jobDetail = new JobDetail("FB_Details", null, FacebookControllerHelper.class);
jobDetail.getJobDataMap().put("Users", user);
jobDetail.getJobDataMap().put("accessToken", accessToken);
jobDetail.getJobDataMap().put("fbService", facebookService);
jobDetail.getJobDataMap().put("OAuth", service);
Trigger trigger = TriggerUtils.makeImmediateTrigger(0, 1);
trigger.setName("FB_Details");
try {
shed.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
System.out.println("Ended In Exception");
e.printStackTrace();
}
FBControllerHelper:
public class FacebookControllerHelper implements Job{
private Users users;
private Token accessToken;
private FacebookService facebookService;
private OAuthService service;
Gson gson = new Gson();
private static final String PROTECTED_RESOURCE_URL_LIKE = "https://graph.facebook.com/me?fields=likes.limit(1000).fields(id,name,description,website)";
public FacebookControllerHelper(){
}
public void execute(JobExecutionContext context)
throws JobExecutionException{
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
users = (Users) dataMap.get("Users");
accessToken = (Token) dataMap.get("accessToken");
facebookService = (FacebookService) dataMap.get("fbService");
service = (OAuthService) dataMap.get("OAuth");
this.getUserLikes(accessToken, users);
}
@Transactional
public void getUserLikes(Token accessToken, Users user){
System.out.println("Entering getUserLikes Method");
OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL_LIKE);
service.signRequest(accessToken, request);
Response response = request.send();
FBUserLikes fbuserLikes = gson.fromJson(response.getBody(), FBUserLikes.class);
System.out.println(response.getBody());
facebookService.saveUserLikes(user, fbuserLikes);
}
}
response.getBody()
正在打印来自facbook的json。但在将其传递给服务时,我正在调用DAO'S save()方法。那时我收到以下错误,
[ERROR] [DefaultQuartzScheduler_Worker-2] org.quartz.core.JobRunShell - Job DEFAULT.FB_Details threw an unhandled Exception:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
我搜索了我的错误,我得到了一些解决方案,这不适合我的应用程序。我使用的是spring 3.0.5 Version和quartz 1.8.6。许多博客和类似的结果向我展示了如何在特定的时间间隔内运行cron作业。但这对我没用。如果有人帮助我解决这个问题,我将不胜感激。希望我的问题很明确。
提前谢谢。
答案 0 :(得分:1)
原因是您从同一个控制器调用transational方法。 Spring需要为transation注释创建代理。您可以通过自动装配或从spring上下文中获取bean来实现,但是您必须将此方法移动到单独的类。
另一个(脏)解决方案是直接在方法中创建hibernate会话。
答案 1 :(得分:1)
因为没有正在进行的事务而抛出HibernateException
。
@Transactional
上的FacebookControllerHelper.getUserLikes(Token accessToken, Users user)
无效。 Spring使用proxies来实现事务行为。但是为了使其工作,FacebookControllerHelper
的生命周期应该由spring管理,而Quartz实例化FacebookControllerHelper
作业则不是这样。您可以使用aspectj代理在spring之外管理的对象,但这对您的用例来说可能有点复杂。
真正的问题可能是您的服务或dao都不是事务性的。 Facebook服务和dao可能是由spring管理的,所以你应该至少制作dao或service transactional。无论如何,在服务层上声明交易是一种很好的做法。
如果您确实要进行FacebookControllerHelper
事务处理,则应使用aspectj,使用TransactionTemplate
或让spring通过配置自定义SchedulerFactory
来管理作业的生命周期。