Преобразование родительского класса в дочерний класс в отдельной таблице для каждой иерархии классов - PullRequest
1 голос
/ 27 февраля 2012

Я пытаюсь настроить пользовательский случай, где у меня есть одна общая форма, которая может обрабатывать все типы UploadedFile пользовательских загрузок. Итак, вот мои настройки:

@Entity(name="UploadedForm")
@Table(name="uploaded_file")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING)
public class UploadedFile implements Serializable{

    /** 
     * 
     */
    private static final long serialVersionUID = -6810328674369487649L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id")
    protected Long id;

    @Column(name="name")
    protected String name = null;

    @Column(name="bytes",unique=true)
    @Lob
    protected byte[] bytes;

    @Column(name="type",nullable=false, updatable=false, insertable=false)
    protected String type;


    @ManyToOne(fetch=FetchType.LAZY, targetEntity=User.class)
    @JoinColumn(name="user_id")
    protected User user;

    @Column(name="date_submitted")
    @Temporal(TemporalType.DATE)
    protected Date dateSubmitted;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public Date getDateSubmitted() {
        return dateSubmitted;
    }
    public void setDateSubmitted(Date dateSubmitted) {
        this.dateSubmitted = dateSubmitted;
    }

    @PrePersist
    @PreUpdate
    public void populateDateSubmitted(){
        this.dateSubmitted = new java.sql.Date(new java.util.Date().getTime());
    }
    public byte[] getBytes() {
        return bytes;
    }
    public void setBytes(byte[] bytes) {
        this.bytes = bytes;
    }
    public String getType() {
        return type;
    }

}


@Entity(name="Document")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorValue(value="Document")
public class DocumentFile extends UploadedFile {

    public void setDateSubmitted(Date dateSubmitted) {
        this.dateSubmitted = dateSubmitted;
    }

    @PrePersist
    @PreUpdate
    public void populateDateSubmitted(){
        this.dateSubmitted = new java.sql.Date(new java.util.Date().getTime());
    }
    public byte[] getBytes() {
        return bytes;
    }
    public void setBytes(byte[] bytes) {
        this.bytes = bytes;
    }
}


@RequestMapping( value="{type}",method=RequestMethod.GET )
    public String showForm(ModelMap model, @PathVariable("type") String type){
        UploadedFile form = null;
        if((model.get("FORM") == null)){
            if(type.equals("document")){
                form =  new DocumentFile();
            }
            else if( type.equals("image")){
                form =  new ImageFile();
            }
        }else{
            form = (UploadedFile)model.get("FORM");
            if(form.getClass() == DocumentFile.class)
                form = (DocumentFile)form;
            else if(form.getClass() == ImageFile.class)
                form = (ImageFile)form;
        }


        model.addAttribute("message", "Please select your file and hit submit.");

        model.addAttribute("FORM", form);

        model.addAttribute("type", type);

        return "upload_form";
    }
    @RequestMapping( method=RequestMethod.POST )
    public String processForm(Model model, @RequestParam(value="type") String type, @ModelAttribute(value="FORM") UploadedFile form,BindingResult result, Principal principal) throws FileSaveException, Exception{
        if(!result.hasErrors()){

            UploadedFile savedFile = null;

            try {
                // Find the currently logged in user.  There has to be a more eloquent way...
                String username = principal.getName();
                User user = uService.findByName(username);

                // Set the associated user to the UploadedFile
                form.setUser(user);

                if(type.equals("document"))
                    form = (DocumentFile)form;
                else if(type.equals("image"))
                    form = (ImageFile)form;

                // Persist the file
                savedFile = this.saveFile(form);
            } catch (Exception e) {

                FileSaveException fse =  new FileSaveException("Unable to save file: " + e.getMessage());

                fse.setStackTrace(e.getStackTrace());

                throw fse;

            }
            model.addAttribute("message", "SUCCESS!");
            model.addAttribute("FORM", savedFile);
            return "upload_success";

        }else{

            return "upload_form";

        }
    }

<%@ include file="/WEB-INF/views/includes.jsp" %>
<%@ page session="false" %>
<%@ include file="/WEB-INF/views/header.jsp" %>
<head>
<title>upload</title>
</head>
<body>
    <h1>Upload Stuff -</h1>
    ${message}
    <br />
    <br />

    <form:form commandName="FORM" action="/upload"
        enctype="multipart/form-data" method="POST">
        <input type="hidden" name="type" value="${ type }"/>
        <table>
            <tr>
                <td colspan="2" style="color: red;"><form:errors path="*"
                        cssStyle="color : red;" /> ${errors}</td>
            </tr>
            <tr>
                <td>Name :</td>
                <td>
                    <form:input type="text" path="name" />
                </td>
            </tr>
            <tr>
                <td>File:</td>
                <td>
                    <form:input type="file" path="bytes" />
                </td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="Upload File" />
                </td>
            </tr>
        </table>
    </form:form>
    <br />
    <a href="/">Go home</a>
</body>
<%@ include file="/WEB-INF/views/footer.jsp"%>

И ошибка, которую я получаю:

Невозможно наложить Объект UploadedFile на DocumentFile

Есть идеи, почему?

ОБНОВЛЕНИЕ: Я нашел обходной путь, не передавая UploadedFile, а передав класс Concrete, который я действительно хочу сохранить. Мне также пришлось удалить методы controller / service / dao и создать один для каждого дочернего файла UploadedFile. Похоже, должен быть лучший способ сделать это. Пожалуйста, дайте ваши предложения. Заранее спасибо! :)

1 Ответ

0 голосов
/ 27 февраля 2012

Похоже, ваша проблема больше связана с Spring, чем с Hibernate. Это:

@ModelAttribute(value="FORM") UploadedFile form

Spring не может знать, когда он переводит входящий запрос, что вы хотите, чтобы он создал DocumentFile вместо UploadedFile. Может быть возможно создать свой собственный ConversionService, но, вероятно, проще просто иметь различные сопоставления запросов для ваших разных форм. Как

@RequestMapping(value="/post/uploadedfile", method=RequestMethod.POST )
public String processUploadedFileForm(Model model, @RequestParam(value="type") String type, @ModelAttribute(value="FORM") UploadedFile form,BindingResult result, Principal principal) throws FileSaveException, Exception{
...
}

@RequestMapping(value="/post/documentfile", method=RequestMethod.POST )
public String processDocumentFileForm(Model model, @RequestParam(value="type") String type, @ModelAttribute(value="FORM") DocumentFile form,BindingResult result, Principal principal) throws FileSaveException, Exception{
...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...