【问题标题】:Error 500: org.hibernate.HibernateException: No Session found for current thread [duplicate]错误 500:org.hibernate.HibernateException:没有为当前线程找到会话 [重复]
【发布时间】:2018-09-24 21:17:14
【问题描述】:

当我尝试在我的项目中上传图片时出现此错误。该项目执行良好,直到它必须有效地将图片上传到数据库(我使用的是 postgresql),但最后一步永远不会工作。

考虑了以下答案,更新了以下代码。

这是我的控制器(它的一部分):

@Autowired
private FileUploadImpl fileUploadImpl;

...

@RequestMapping(value = "publish4" ,method = RequestMethod.POST)
public ModelAndView publish4(@Valid @ModelAttribute("fourthPublicationForm") final FourthPublicationForm form, final BindingResult errors,
                             @RequestParam("type") String type, @RequestParam("operation") String operation , @RequestParam CommonsMultipartFile[] fileUpload) {
    if (errors.hasErrors()) {
        //return helloPublish3(form,operation,type);
    }
    System.out.println("operation: "+ operation);
    System.out.println("type: "+ type);
    ps.create(form.getTitle(), form.getAddress(), operation, form.getPrice(), form.getDescription(), 
            type, form.getBedrooms(), form.getBathrooms(), form.getFloorSize(), form.getParking());

    if (fileUpload != null && fileUpload.length > 0) {
        for (CommonsMultipartFile aFile : fileUpload){

            System.out.println("Saving file: " + aFile.getOriginalFilename());

            UploadFile uploadFile = new UploadFile();
            uploadFile.setAddress(form.getAddress());
            uploadFile.setData(aFile.getBytes());
            fileUploadImpl.save(uploadFile);               
        }
    }
    return new ModelAndView("redirect:/hello/home");
}

这是界面中的fileUploadDao:

public interface FileUploadDao {
   void save(UploadFile uploadFile);
}

这是在服务中:

@Service
public class FileUploadImpl {

    @Autowired
    private FileUploadDao fileUploadDao;

    public FileUploadImpl() {
    }

    @Transactional
    public void save(UploadFile uploadFile) {
        fileUploadDao.save(uploadFile);
    }

}

以下坚持:

@Repository
public class FileUploadDAOImpl implements FileUploadDao {
    @Autowired
    private SessionFactory sessionFactory;

    public FileUploadDAOImpl() {
    }

    public FileUploadDAOImpl(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }


    public void save(UploadFile uploadFile) {
       sessionFactory.getCurrentSession().save(uploadFile);
    }
}

我在 WebConfig.java 中得到了这个(以及其他东西)

@Bean
public LocalSessionFactoryBean sessionFactory() {
   LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
   sessionFactory.setDataSource(dataSource());
   sessionFactory.setPackagesToScan(
       new String[] { "ar.edu.itba.paw" }
   );
   //sessionFactory.setHibernateProperties(hibernateProperties());

   return sessionFactory;
}

@Autowired
@Bean(name = "fileUploadDao")
public FileUploadDao getUserDao(SessionFactory sessionFactory) {
    return new FileUploadDAOImpl(sessionFactory);
}

@Bean(name = "multipartResolver")
public CommonsMultipartResolver getCommonsMultipartResolver() {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(20971520);   // 20MB
    multipartResolver.setMaxInMemorySize(1048576);  // 1MB
    return multipartResolver;
}

@Bean
@Autowired
public HibernateTransactionManager transactionManager(
    SessionFactory sessionFactory) {
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(sessionFactory);
    return txManager;
}

更多一点的错误:

org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
at ar.edu.itba.paw.persistence.FileUploadDAOImpl.save(FileUploadDAOImpl.java:25)
at ar.edu.itba.paw.webapp.controller.HelloWorldController.publish4(HelloWorldController.java:260)

我看到其他问题的答案是没有使用“事务性”。我在这里使用该注释,但我不确定它的方式是否 100% 正确。

【问题讨论】:

  • @OldPro 我已经尝试过那里的解决方案,但它们似乎不起作用,或者我可能不太了解它们。

标签: java spring hibernate spring-mvc sessionfactory


【解决方案1】:

首先从FileUploadDAOImpl 中删除@Transactional

相应地更改基础包,

sessionFactory.setPackagesToScan(
   new String[] { "base.package.to.scan" } 
);

base.package.to.scan 似乎是无效的基础包命名,请将其更改为 ar.edu.itba.paw

您需要一个事务管理器才能使用@Transactional。添加到WebConfig

@Bean
@Autowired
public HibernateTransactionManager transactionManager(
    SessionFactory sessionFactory) {
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(sessionFactory());
    return txManager;
}

这可能会让这段代码工作,试一试。

更新:还要确保WebConfig 类上存在以下注释,

@Configuration
@ComponentScan({"ar.edu.itba.paw"})
@EnableTransactionManagement(mode = AdviceMode.PROXY)
public class WebConfig {
    // code
}

【讨论】:

  • 谢谢,基本包肯定是错误的。我已经使用您的答案更新了上面的代码。我仍然得到完全相同的异常。
  • @Stackoverflowed 旁注:因为您使用字段自动装配依赖于 sessionFactory,所以在 WebConfig.java 中不需要 getUserDao 方法
  • @Stackoverflowed 您是否在WebConfig.java 类上添加了所需的注释?请查看更新。
  • 我添加了不带模式的@EnableTransactionManagement,因为我可以解决 AdviceMode(也许我需要依赖或其他什么?)。无论如何修复了异常,我得到了一个新的“org.hibernate.exception.SQLGrammarException:无法提取结果集”,但这可能是另一个问题。非常感谢。
【解决方案2】:

正如你从一开始就说的,你混淆了实际的层。你仍然可以让它在你的情况下正常工作,但让我们讨论一下你的实现。

  • FileUploadDao 是 DAO 还是服务?
  • FileUploadImpl 似乎您将 @Service@Repository 混淆了, 也许读出来可能会对你有所帮助。 Spring Data Repositories , Spring Service Annotation
  • 您创建了一个事务方法,save,我无法准确地说出您想要实现的目标。您还自动装配FileUploadDaoSessionFactory,尽管您想实现第一个和内部方法,您试图通过首先在存储库上调用save 来两次持久化对象(这是第一个的StackOverflowError地方,但你很幸运,因为 Spring 知道要自动装配什么)然后你试图在 Hibernate 的 SessionFactory 上再次调用 save ,这违反了抽象的 JPA 合同。此外,如果您注意到,您发布的日志中的错误来自第二次保存。
  • @Transactional 不打算讨论这是如何工作的,因为你还没有发布你的整个应用程序配置。但同样,您可以阅读this 了解更多信息。

因此,根据您分享的示例,我将准备 2 个案例,这可能有助于您了解下面发生的事情。

  1. 第一种情况,Spring DATA,并不关心它的 Hibernate 还是下面的另一个 JPA 提供程序。

您的FileUploadImpl 变为:FileUploadService

@Service
public class FileUploadService {

    @Autowired
    private FileUploadDao fileUploadDao;

    public FileUploadService() {
    }

    @Transactional
    public void save(UploadFile uploadFile) {
        fileUploadDao.save(uploadFile);
    }

}

在您的控制器内部,您正在自动装配服务(层)而不是直接装配存储库/DAO(层)。没有什么能阻止你,这只是设计问题(如果你仍然不明白这一点,请提出另一个问题)。

你的部分控制器的一部分

    @Autowired
    private FileUploadService fileUploadService;


    @RequestMapping(value = "publish4" ,method = RequestMethod.POST)
    public ModelAndView publish4(@Valid @ModelAttribute("fourthPublicationForm") final FourthPublicationForm form, final BindingResult errors,
                             @RequestParam("type") String type, @RequestParam("operation") String operation , @RequestParam CommonsMultipartFile[] fileUpload) {
       .........
       fileUploadService.save(uploadFile);   
}
  1. 第二种情况,如果你真的想使用hibernate的好东西,那么没有任何理由自动装配Repository,而只需自己实现这些调用。
导入 org.springframework.stereotype.Component; @零件 公共类 FileUploadDao { @自动连线 私人 SessionFactory 会话工厂; 公共文件上传保存(文件上传 obj){ 返回 sessionFactory.getCurrentSession().save(obj); } 公共文件上传合并(文件上传 obj){ 返回 sessionFactory.getCurrentSession().merge(obj); } .....删除/更新/或自定义查询(SQL/JPQL/HQL)可以放在这里 }

您的服务只是公开了这些方法,检查差异,我在这一层上应用了@Transactional 注释(你可以再次将它放在 DAO 层中,但正如我所说,这是设计问题)。

@服务
公共类 FileUploadService {

    @自动连线
    私有 FileUploadDao 文件UploadDao;

    公共文件上传服务(){
    }

    @Transactional
    公共上传文件保存(上传文件上传文件){
        fileUploadDao.save(uploadFile);
    }

    @Transactional
    公共上传文件合并(上传文件上传文件){
        fileUploadDao.merge(uploadFile);
    }

    ....您要公开的其他方法,或多个 DAO 的组合

}

你的控制器保持不变,这就是你需要层的真正原因。

【讨论】:

  • 感谢您的宝贵时间。不幸的是,我无法让它工作。第一个替代方案抛出相同的异常,第二个替代方案在我运行项目时引发异常(自动装配依赖项的注入失败......)。我已经更新了我的代码,提供了更多细节,也许我还缺少其他东西。
  • 我刚刚使用您提供的帮助(第一个替代方案)和我之前忘记的持久层代码更新了我的问题。我还添加了 webconfig。
  • 我用那个名字留下了 FileUploadImpl 但我改变了你所说的一切。
  • @Stackoverflowed 在您的控制器中,您在自动装配哪个 dao ?从发布的原因中,我可以看到您正在显式注入 FileUploadImpl。
猜你喜欢
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
  • 2015-05-28
  • 2014-09-29
  • 2014-01-10
  • 1970-01-01
  • 2013-06-21
相关资源
最近更新 更多