当我尝试在项目中上传图片时出现此错误。项目必须执行良好,直到必须将图片有效地上传到数据库为止(我使用的是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%正确。
答案 0 :(得分:2)
首先从@Transactional
中删除FileUploadDAOImpl
。
相应地更改基本软件包,
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
}
答案 1 :(得分:1)
正如您从一开始所说的,您已经混淆了实际的图层。仍然可以使它在您的情况下正常工作,但让我们讨论一下您的实现。
FileUploadDao
是DAO还是服务?FileUploadImpl
似乎使@Service
与@Repository
混淆,
也许读出来可能对您有帮助。 Spring Data Repositories,Spring Service Annotation save
,在其中我无法说出您想要实现的目标。您还同时自动装配了FileUploadDao
和SessionFactory
,尽管您想实现方法的第一个和内部方法,但都试图通过首先在存储库上调用save
来两次持久化对象(即StackOverflowError
首先是您,但您很幸运,因为Spring知道如何自动连线),然后您尝试再次调用Hibernate的SessionFactory进行保存,这破坏了抽象的JPA契约。另外,如果您注意到了,则您发布的日志中的错误来自第二次保存。@Transactional
不会讨论这是如何工作的,因为您尚未发布整个应用程序配置。但同样,您可以阅读this了解更多信息。因此,基于您共享的示例,我将准备2个案例,这些案例可能有助于您了解底层情况。
您的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);
}
import org.springframework.stereotype.Component;
@Component
public class FileUploadDao {
@Autowired
private SessionFactory sessionFactory;
public FileUpload save(FileUpload obj) {
return sessionFactory.getCurrentSession().save(obj);
}
public FileUpload merge(FileUpload obj) {
return sessionFactory.getCurrentSession().merge(obj);
}
..... delete / update / or custom queries(SQL/JPQL/HQL) can be placed here
}
Your service simply exposes those methods , check the difference , i am applying the @Transactional
annotation on this layer(ofc again you can put it in the DAO layer, but as i said its a matter of design).
@Transactional
您的控制器保持不变,这就是您需要分层的实际原因。