Java 错误500:org.hibernate.HibernateException:未找到当前线程的会话

Java 错误500:org.hibernate.HibernateException:未找到当前线程的会话,java,spring,hibernate,spring-mvc,sessionfactory,Java,Spring,Hibernate,Spring Mvc,Sessionfactory,当我尝试在项目中上载图片时,出现此错误。项目执行得很好,直到它必须有效地将图片上传到数据库(我使用的是postgresql),但这最后一步永远不起作用 在考虑了以下答案后,更新了以下代码 这是我的控制器(它的一部分): 这是接口中的fileUploadDao: public interface FileUploadDao { void save(UploadFile uploadFile); } 这是在服务: @Service public class FileUploadImpl {

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

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

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

这是接口中的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中得到了这个(还有其他东西)

还有一点错误:

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%正确

正如您从一开始所说的,您混淆了实际的图层。尽管如此,您仍然可以使它在您的情况下正常工作,但让我们讨论一下您的实现

  • fileuploadao
    它是DAO还是服务
  • FileUploadImpl
    似乎将
    @Service
    @Repository
    混淆了, 也许读出来会对你有所帮助
  • 您已经创建了一个事务性方法,
    save
    ,在该方法中,我无法确切说明您想要实现什么。您还可以自动连接
    FileUploadDao
    SessionFactory
    ,尽管您希望实现第一个方法,并在该方法内部尝试通过首先在存储库上调用
    save
    来保存对象两次(这是一个
    StackOverflowerError
    ,但是你很幸运,因为Spring知道自动连线什么)然后你试图在Hibernate的SessionFactory上再次调用save,这打破了抽象的JPA契约。另外,如果你注意到,你发布的日志中的错误,来自第二次保存
  • @Transactional
    不会讨论这是如何工作的,因为您还没有发布整个应用程序配置。不过,您可以阅读更多信息
根据你们分享的例子,我准备两个案例,这可能会帮助你们理解下面发生的事情

  • 第一种情况是,Spring数据,并不真正关心它的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);   
    }
    
  • 第二种情况,如果您真的想使用hibernate goodies,那么没有任何理由自动连接存储库,只需自己实现这些调用即可

  • 您的控制器保持不变,这就是您需要层的实际原因。

    正如您从一开始所说的,您已经混淆了实际的层。您仍然可以使其在您的情况下正常工作,但让我们讨论一下您的实现

    • fileuploadao
      它是DAO还是服务
    • FileUploadImpl
      似乎将
      @Service
      @Repository
      混淆了, 也许读出来会对你有所帮助
    • 您已经创建了一个事务性方法,
      save
      ,在这个方法中,我无法确切地说出您想要实现什么。您还自动连接了
      fileuploadao
      SessionFactory
      ,尽管您想要实现第一个方法,并且在该方法内部,您尝试通过首先调用
      save
      来持久化对象两次存储库(从一开始就是一个
      StackOverflowerError
      ,但是您很幸运,因为Spring知道自动连线什么)然后,您尝试在Hibernate的SessionFactory上再次调用save,这打破了抽象的JPA约定
    • @Transactional
      不会讨论这是如何工作的,因为您还没有发布整个应用程序配置。不过,您可以阅读更多信息
    根据你们分享的例子,我准备两个案例,这可能会帮助你们理解下面发生的事情

  • 第一种情况是,Spring数据,并不真正关心它的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);   
    }
    
  • 第二种情况,如果您真的想使用hibernate goodies,那么没有任何理由自动连接存储库,只需自己实现这些调用即可

  • 您的控制器保持不变,这就是您需要图层的实际原因。

    首先从
    fileuploadaoimpl
    中删除
    @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
    class上有以下注释

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

    首先从
    fileuploadaoimpl
    中删除
    @Transactional

    相应地更改基本包

    sessionFactory.setPackagesToScan(
       new String[] { "base.package.to.scan" } 
    );
    
    base.package.to.scan
    似乎是无效的基本包命名,请将其更改为
    ar.edu.itba.paw

    您需要事务管理器才能使用
    @Transact
    
    @Configuration
    @ComponentScan({"ar.edu.itba.paw"})
    @EnableTransactionManagement(mode = AdviceMode.PROXY)
    public class WebConfig {
        // code
    }