无法在Spring中将MultipartFile转换为Blob
我正在尝试将上传的文件保存为MySql记录中的Blob。我是春天的新手。当我在上传文件后准备保存记录时,当我的POST方法无法在Spring中将MultipartFile转换为Blob,spring,file,spring-mvc,blob,multipartform-data,Spring,File,Spring Mvc,Blob,Multipartform Data,我正在尝试将上传的文件保存为MySql记录中的Blob。我是春天的新手。当我在上传文件后准备保存记录时,当我的POST方法updateCandidate()执行时,我会出现以下异常: 字段“cv”上的对象“candidateForm”中的字段错误:拒绝值[org.springframework.web.multipart.support.StandardMultipartTTPServletRequest$StandardMultipartFile@59c09df6]; 代码[typeMisma
updateCandidate()
执行时,我会出现以下异常:
字段“cv”上的对象“candidateForm”中的字段错误:拒绝值[org.springframework.web.multipart.support.StandardMultipartTTPServletRequest$StandardMultipartFile@59c09df6]; 代码[typeMismatch.candidateForm.cv、typeMismatch.cv、typeMismatch.java.sql.Blob、typeMismatch];参数[org.springframework.context.support.DefaultMessageSourceResolvable:代码[candidateForm.cv,cv];参数[];默认消息[cv];默认消息[未能将类型为'org.springframework.web.multipart.support.StandardMultipartTtpServletRequest$StandardMultipartFile'的属性值转换为属性'cv'所需的类型'java.sql.Blob';嵌套异常为java.lang.IllegalStateException:无法转换类型为'org.springframework.web.multipart.support.StandardMultipartTtpServlet'的值请求$StandardMultipartFile'为属性“cv”的必需类型“java.sql.Blob”:未找到匹配的编辑器或转换策略]
出了什么问题?如何修复
我的实体:
import java.sql.Blob;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
@Entity
public class Candidate {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(unique = true)
private String ssn;
private String name;
private String surname;
private String technology;
private String media;
@Lob
private Blob cv;
private boolean activeCV;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getTechnology() {
return technology;
}
public void setTechnology(String technology) {
this.technology = technology;
}
public String getMedia() {
return media;
}
public void setMedia(String media) {
this.media = media;
}
public Blob getCv() {
return cv;
}
public void setCv(Blob cv) {
this.cv = cv;
}
public boolean isActiveCV() {
return activeCV;
}
public void setActiveCV(boolean activeCV) {
this.activeCV = activeCV;
}
}
为我服务:
@Autowired
private CandidateRepository repository;
...
public Optional<Candidate> getCandidate(Long id){
return repository.findById(id);
}
public void addOrUpdateCandidate(Candidate candidate) {
repository.save(candidate);
}
My updateCandidateForm.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<body>
<form:form method="POST" action="updateCandidateResult" modelAttribute="candidateForm" enctype="multipart/form-data">
<form:hidden path="id"/>
<table>
<tr>
<td><form:label path="name">Name</form:label></td>
<td><form:input path="name"/></td>
</tr>
<tr>
<td><form:label path="surname">Surname</form:label></td>
<td><form:input path="surname"/></td>
</tr>
<tr>
<td><form:label path="ssn">SSN</form:label></td>
<td><form:input path="ssn"/></td>
</tr>
<tr>
<td><form:label path="technology">Known Technology</form:label></td>
<td><form:input path="technology"/></td>
</tr>
<tr>
<td><form:label path="media">Found us on</form:label></td>
<td><form:input path="media"/></td>
</tr>
<tr>
<td><form:label path="cv">Select a cv</form:label></td>
<td><input type="file" name="cv" /></td>
</tr>
<tr>
<td><form:label path="activeCV">Active CV</form:label></td>
<td><form:checkbox path="activeCV" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit"/></td>
</tr>
</table>
</form:form>
</body>
在controller中,现在我首先关心的是pojo是否可以正确实例化,因此我的GET-POST对是:
@GetMapping("/updateCandidate/{id}")
public String showUpdateUserForm(@PathVariable("id") Long id, Model model) {
CandidatePOJO candidatePOJO = new CandidatePOJO();
candidatePOJO.setId(id);
model.addAttribute("candidateForm", candidatePOJO);
return "updateCandidateForm";
}
@PostMapping("/updateCandidate/updateCandidateResult")
public String updateCandidate(@ModelAttribute("candidateForm") CandidatePOJO candidatePOJO) {
System.out.println("CANDIDATE POJO");
System.out.println(candidatePOJO.toString()); // here I notice id = null
/* MultipartFile to Blob conversion */
// MultipartFile file = candidatePOJO.getCv();
// InputStream iStream = file.getInputStream();
// long size = file.getSize();
// Session session = emf.unwrap(Session.class);
// Blob cv = Hibernate.getLobCreator(session).createBlob(iStream, size);
/* instantiating the entity object to be freezed in db */
// Candidate candidate = new Candidate();
// set all data from candidatePOJO..
// candidate.setCv(cv);
// service.addOrUpdateCandidate(candidate);
return "updateCandidateResult";
}
我得到了一个没有id设置的CandidatePOJO对象。我无法获得从get到POST的id通行证。有人知道怎么了吗
编辑3:
在我选择了支持POJO的解决方案很多天后,难以置信的是,我注意到ID从GET方法传递到POST方法(我没有做任何更改,我只是执行了经典的Maven项目清理,就像我发布问题时那样)。不幸的是,我现在面临另一个例外(当然,在恢复先前在POST方法中注释的代码之后):
javax.persistence.PersistenceException:Hibernate无法将EntityManagerFactory作为“org.Hibernate.Session”展开
如何解决这个问题
编辑4:
正上方的异常已解决替换:
Session session = emf.unwrap(Session.class);
与:
通过使用SUPPORT POJO,我终于解决了问题。事实上,我之前已经通过代码解决了问题。文章中的代码是正确的(EDIT 2)。当我经常执行Maven项目清理时,这并没有发现错误。我在过去几个小时内执行了清理,我的代码工作得令人难以置信。我猜不出神奇之处:D我不知道到底发生了什么。通过代码,我用两种不同的方式解决了问题。首先:
@Autowired
private EntityManagerFactory emf;
// ........
@GetMapping("/updateCandidate/{id}")
public String showUpdateUserForm(@PathVariable("id") Long id, Model model) {
Candidate candidate = service.getCandidate(id).get();
CandidatePOJO candidatePOJO = new CandidatePOJO();
candidatePOJO.setId(id);
candidatePOJO.setName(candidate.getName());
candidatePOJO.setSurname(candidate.getSurname());
candidatePOJO.setSsn(candidate.getSsn());
candidatePOJO.setMedia(candidate.getMedia());
candidatePOJO.setTechnology(candidate.getTechnology());
candidatePOJO.setActiveCV(candidate.isActiveCV());
model.addAttribute("candidateForm", candidatePOJO);
return "updateCandidateForm";
}
@PostMapping("/updateCandidate/updateCandidateResult")
public String updateCandidate(@ModelAttribute("candidateForm") CandidatePOJO candidatePOJO) throws IOException {
MultipartFile file = candidatePOJO.getCv();
InputStream iStream = file.getInputStream();
long size = file.getSize();
EntityManager em = emf.createEntityManager();
Session session = (Session) em.getDelegate();
Blob cv = Hibernate.getLobCreator(session).createBlob(iStream, size);
Candidate candidate = new Candidate();
candidate.setId(candidatePOJO.getId());
candidate.setName(candidatePOJO.getName());
candidate.setSurname(candidatePOJO.getSurname());
candidate.setSsn(candidatePOJO.getSsn());
candidate.setMedia(candidatePOJO.getMedia());
candidate.setTechnology(candidatePOJO.getTechnology());
candidate.setActiveCV(candidatePOJO.isActiveCV());
candidate.setCv(cv);
service.addOrUpdateCandidate(candidate);
return "updateCandidateResult";
}
第二(使用相同的GET):
作为Spring的新手,我还不知道它们之间的区别。我希望有更多的解释。此外,我想修改这段代码,以摆脱对POJO的支持,只处理实体对象:如果有人能解决我最初的问题,我将永远感激!例外说明一切:您的方法已经成功了候选对象作为参数,因此Spring应该根据请求的参数填充其属性。但它不能从您发送的多部分文件中填充Blob类型的属性。只是不要将您的持久实体用于候选表单。请使用专用类,它代表客户端发送的内容,而不是数据库行包含。我被限制使用Blob作为该字段类型。因此,如果我做得好,它会在POST开始执行时尝试转换,当它无法执行时会停止转换,因此它甚至无法详细说明我的编码转换(?。您能写一些代码吗?:)创建一个类。一个简单的POJO,包含表单发送的每个参数的getter和setter,以及相应的类型。使用该类,而不是候选类作为命令。应用必要的转换,将此命令对象中的数据复制到实体中。Hello@JBNizet,我使用了一个POJO,正如您所说的。如果我编写了corre实际上,系统抛出了相同的异常,确认了我的信念,即它不是对象的类型(实体bean,POJO)这会造成混乱。如果我确实编码错误,我想找出正确的做法。我想告诉你我是如何编辑我的GET和POST的。我不知道如何打开这里的聊天框。请原谅我可能的英语错误。谢谢,我省略了一些东西。现在它部分工作。我可以让系统实例化t他有一个候选POJO(cv类型不是Blob,而是MultipartFile),但它没有设置id,所以我的帖子检索一个未设置字段的对象
@GetMapping("/updateCandidate/{id}")
public String showUpdateUserForm(@PathVariable("id") Long id, Model model) {
CandidatePOJO candidatePOJO = new CandidatePOJO();
candidatePOJO.setId(id);
model.addAttribute("candidateForm", candidatePOJO);
return "updateCandidateForm";
}
@PostMapping("/updateCandidate/updateCandidateResult")
public String updateCandidate(@ModelAttribute("candidateForm") CandidatePOJO candidatePOJO) {
System.out.println("CANDIDATE POJO");
System.out.println(candidatePOJO.toString()); // here I notice id = null
/* MultipartFile to Blob conversion */
// MultipartFile file = candidatePOJO.getCv();
// InputStream iStream = file.getInputStream();
// long size = file.getSize();
// Session session = emf.unwrap(Session.class);
// Blob cv = Hibernate.getLobCreator(session).createBlob(iStream, size);
/* instantiating the entity object to be freezed in db */
// Candidate candidate = new Candidate();
// set all data from candidatePOJO..
// candidate.setCv(cv);
// service.addOrUpdateCandidate(candidate);
return "updateCandidateResult";
}
Session session = emf.unwrap(Session.class);
EntityManager em = emf.createEntityManager();
Session session = (Session) em.getDelegate();
@Autowired
private EntityManagerFactory emf;
// ........
@GetMapping("/updateCandidate/{id}")
public String showUpdateUserForm(@PathVariable("id") Long id, Model model) {
Candidate candidate = service.getCandidate(id).get();
CandidatePOJO candidatePOJO = new CandidatePOJO();
candidatePOJO.setId(id);
candidatePOJO.setName(candidate.getName());
candidatePOJO.setSurname(candidate.getSurname());
candidatePOJO.setSsn(candidate.getSsn());
candidatePOJO.setMedia(candidate.getMedia());
candidatePOJO.setTechnology(candidate.getTechnology());
candidatePOJO.setActiveCV(candidate.isActiveCV());
model.addAttribute("candidateForm", candidatePOJO);
return "updateCandidateForm";
}
@PostMapping("/updateCandidate/updateCandidateResult")
public String updateCandidate(@ModelAttribute("candidateForm") CandidatePOJO candidatePOJO) throws IOException {
MultipartFile file = candidatePOJO.getCv();
InputStream iStream = file.getInputStream();
long size = file.getSize();
EntityManager em = emf.createEntityManager();
Session session = (Session) em.getDelegate();
Blob cv = Hibernate.getLobCreator(session).createBlob(iStream, size);
Candidate candidate = new Candidate();
candidate.setId(candidatePOJO.getId());
candidate.setName(candidatePOJO.getName());
candidate.setSurname(candidatePOJO.getSurname());
candidate.setSsn(candidatePOJO.getSsn());
candidate.setMedia(candidatePOJO.getMedia());
candidate.setTechnology(candidatePOJO.getTechnology());
candidate.setActiveCV(candidatePOJO.isActiveCV());
candidate.setCv(cv);
service.addOrUpdateCandidate(candidate);
return "updateCandidateResult";
}
@PostMapping("/updateCandidate/updateCandidateResult")
public String updateCandidate(@ModelAttribute("candidateForm") CandidatePOJO candidatePOJO) throws IOException, SerialException, SQLException {
MultipartFile file = candidatePOJO.getCv();
Blob cv = new SerialBlob(file.getBytes());
Candidate candidate = new Candidate();
candidate.setId(candidatePOJO.getId());
candidate.setName(candidatePOJO.getName());
candidate.setSurname(candidatePOJO.getSurname());
candidate.setSsn(candidatePOJO.getSsn());
candidate.setMedia(candidatePOJO.getMedia());
candidate.setTechnology(candidatePOJO.getTechnology());
candidate.setActiveCV(candidatePOJO.isActiveCV());
candidate.setCv(cv);
service.addOrUpdateCandidate(candidate);
return "updateCandidateResult";
}