无法更新实体

时间:2018-01-03 13:52:52

标签: spring-boot vue.js

我正在尝试使用特定映射更新实体:

@Entity
@Table(name = "obs_structure2")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Structure implements Serializable{
    private String id;
    private String tag;
    private String description;
    private Set<Version> parentVersions = new HashSet<>();
    private List<StructureElement> children = new ArrayList<>();
    private List<StructureElement> slaves = new ArrayList<>();
    private PersistenceSignature signature = new PersistenceSignature();

    @OneToMany(mappedBy = "parentStructure")
    public List<StructureElement> getChildren() {
        return children;
    }

    public void addChild(StructureElement se)
    {
        if(this.children.contains(se))
        {
            this.children.add(se);
        }
    }

@Entity
@Table(name = "obs_structure_element2")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class StructureElement implements Serializable{
    private long id;
    private String tag;
    private String description;
    private boolean repetitive = false;
    private boolean optional = false;
    private Integer position = 1;
    private Structure parentStructure;
    private Structure typeStructure;
    private PersistenceSignature signature = new PersistenceSignature();

    @ManyToOne
    @JoinColumn(name = "parent_id")
    @JsonIgnore
    public Structure getParentStructure() {
        return parentStructure;
    }

这是我的控制者:

   @PutMapping("/update")
    public StructureElement update(@RequestBody StructureElement se){
        logger.info("Call to StructureElementController.update with se = " + se);
        this.connectToDatabase();
        StructureElement updatedSE;
        try{
            boolean exists = this.repository.exists(se.getId());
            if(!exists){
                logger.error("Could not find StructureElement to update. se = " + se);
                return null;
            }
            updatedSE = this.repository.save(se);
            logger.info("Updated SE = " + updatedSE);
        }catch (Exception e){
            logger.error("Could not update structure element. se = " + se, e);
            return null;
        }
        return updatedSE;
    }

当我尝试更新元素时​​,parentStructure被覆盖为空。

如果我删除了@JsonIgnore注释,我收到此StackOverflow错误:

[ERROR] 2018-01-03 14:22:38.577 [http-nio-8080-exec-5] o.a.c.c.C.[.[.[.[dispatcherServlet] 181 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause
java.lang.StackOverflowError: null
    at java.util.AbstractCollection.toString(AbstractCollection.java:454) ~[?:1.8.0_151]
    at java.lang.String.valueOf(String.java:2994) ~[?:1.8.0_151]
    at java.lang.StringBuilder.append(StringBuilder.java:131) ~[?:1.8.0_151]
    at be.groups.observatory.server.model.Structure.toString(Structure.java:147) ~[classes/:?]
    at java.lang.String.valueOf(String.java:2994) ~[?:1.8.0_151]
    at java.lang.StringBuilder.append(StringBuilder.java:131) ~[?:1.8.0_151]
    at be.groups.observatory.server.model.StructureElement.toString(StructureElement.java:116) ~[classes/:?]
    at java.lang.String.valueOf(String.java:2994) ~[?:1.8.0_151]
    at java.lang.StringBuilder.append(StringBuilder.java:131) ~[?:1.8.0_151]
    at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[?:1.8.0_151]
    at java.lang.String.valueOf(String.java:2994) ~[?:1.8.0_151]
    at java.lang.StringBuilder.append(StringBuilder.java:131) ~[?:1.8.0_151]
    at be.groups.observatory.server.model.Structure.toString(Structure.java:147) ~[classes/:?]
    at java.lang.String.valueOf(String.java:2994) ~[?:1.8.0_151]
    at java.lang.StringBuilder.append(StringBuilder.java:131) ~[?:1.8.0_151]
    at be.groups.observatory.server.model.StructureElement.toString(StructureElement.java:116) ~[classes/:?]
    at java.lang.String.valueOf(String.java:2994) ~[?:1.8.0_151]
    at java.lang.StringBuilder.append(StringBuilder.java:131) ~[?:1.8.0_151]
    at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[?:1.8.0_151]
    at java.lang.String.valueOf(String.java:2994) ~[?:1.8.0_151]
    at java.lang.StringBuilder.append(StringBuilder.java:131) ~[?:1.8.0_151]
    at be.groups.observatory.server.model.Structure.toString(Structure.java:147) ~[classes/:?]

对于那些知道vue.js的人来说,这是我的组成部分:

<template>
    <div class="t-body">
        <obs-sidebar></obs-sidebar>
        <main class="t-content">

            <div v-if="updated" class="c-notification c-notification--success" role="dialog" aria-label="first notification" aria-describedby="desc_1">
                <p id="desc_1" class="c-notification__message">L'élément de structure à bien été mise à jour.</p>
            </div>

            <div v-if="errors && errors.length">
                <div v-for="error of errors" class="c-notification c-notification--danger">
                    {{ error.message }}
                </div>
            </div>

            <div class="l-row l-row--gutter">
                <div class="l-col">
                    <h1>{{ msg }} - {{ element_id }}</h1>
                </div>
            </div>

            <loader v-if="visible"></loader>

            <div class="l-row l-row--gutter" v-else>
                <div class="l-col-4">
                    <form class="c-form full-width" @submit.prevent="updateStructureElement">
                        <div class="l-row">
                            <fieldset class="c-form__fieldset">
                                <legend class="c-form__legend">Remplissez le formulaire</legend>

                                <div class="l-row nice-top">
                                    <div class="l-col-3 l-justify--end nice-right">
                                        <div class="c-form__field-group">
                                            <label for="tag" class="c-form__label">Tag <span class="s-text s-text--danger">* </span></label>
                                        </div>
                                    </div>
                                    <div class="l-col-7">
                                        <div class="c-form__field-group full-width">
                                            <input id="tag" class="c-form__field full-width" type="text" name="tag" v-model="element.tag"/>
                                        </div>
                                    </div>
                                </div>

                                <div class="l-row nice-top">
                                    <div class="l-col-3 l-justify--end nice-right">
                                        <div class="c-form__field-group">
                                            <label for="description" class="c-form__label">Description <span class="s-text s-text--danger">* </span></label>
                                        </div>
                                    </div>
                                    <div class="l-col-7">
                                        <div class="c-form__field-group full-width">
                                            <textarea id="description" class="c-form__field minimal-h" name="description" v-model="element.description"></textarea>
                                        </div>
                                    </div>
                                </div>

                                <div class="l-row nice-top">
                                    <div class="l-col-6 l-justify--end nice-right">
                                        <div class="c-form__field-group">
                                            <label for="optional" class="c-form__label">Optional <span class="s-text s-text--danger">* </span></label>
                                        </div>
                                    </div>
                                    <div class="l-col-6">
                                        <div class="c-form__field-group">
                                            <input id="optional" class="c-form__field" type="checkbox" name="optional" v-model="element.optional"/>
                                        </div>
                                    </div>
                                </div>

                                <div class="l-row nice-top">
                                    <div class="l-col-6 l-justify--end nice-right">
                                        <div class="c-form__field-group">
                                            <label for="repetitive" class="c-form__label">Répétitif <span class="s-text s-text--danger">* </span></label>
                                        </div>
                                    </div>
                                    <div class="l-col-6">
                                        <div class="c-form__field-group full-width">
                                            <input id="repetitive" class="c-form__field" type="checkbox" name="repetitive" v-model="element.repetitive"/>
                                        </div>
                                    </div>
                                </div>

                            </fieldset>
                        </div>

                        <div class="l-row nice-top">
                            <div class="l-col-offset-3 l-col-7">
                                <button class="c-btn c-btn--primary c-btn--raised c-btn--ripple c-form__button full-width s-text--center" type="submit">Soumettre</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </main>
    </div>
</template>

<script>
    import Loader from 'gso-loader';
    import {state, show, hide} from 'gso-loader/store';
    import {HTTP} from '../http-common';
    import ObsSidebar from './parts/sidebar.vue';

    export default{
        name: 'update-structure-element',
        props: ['element_id'],
        data() {
            return {
                msg: 'Mise à jour de l\'élément',
                element: [],
                errors: [],
                updated: false
            };
        },
        computed: {
            visible() {
                return state.visible;
            }
        },
        methods: {
            updateStructureElement: function () {
                let seToUpdate = this.element;
                console.log('To update = ' + JSON.stringify(seToUpdate));
                HTTP.put('structure-element/update', seToUpdate, {headers: {'Content-Type': 'application/json'}})
                    .then(response => {
                        console.log('response = ' + response);
                        this.element = response.data;
                        this.updated = true;
                    })
                    .catch(e => {
                        console.log('Error = ' + e);
                        this.errors.push(e);
                    });
            }
        },
        components: {ObsSidebar, Loader},
        created() {
            show();
            let elementId = this.$route.params.element_id;
            HTTP.get('structure-element/' + elementId)
                .then(response => {
                    this.element = response.data;
                    hide();
                })
                .catch(e => {
                    this.errors.push(e);
                    hide();
                });
        }
    };
</script>

1 个答案:

答案 0 :(得分:0)

好吧,我正在查看一些文章,并改变了我更新实体的方式:

@PutMapping("/update")
public StructureElement update(@RequestBody StructureElement se){
    StructureElement databaseElement;
    logger.info("Call to StructureElementController.update with se = " + se);
    this.connectToDatabase();
    try{
        databaseElement = this.repository.findOne(se.getId());

        if(databaseElement == null){
            logger.error("Could not find StructureElement to update. se = " + se);
            return null;
        }

        // Update
        databaseElement.setDescription(se.getDescription());
        databaseElement.setTag(se.getTag());
        databaseElement.setOptional(se.isOptional());
        databaseElement.setRepetitive(se.isRepetitive());
        databaseElement.getSignature().setModificationDate(new Date());

        databaseElement = this.repository.save(databaseElement);
        logger.info("Updated SE = " + databaseElement);
    }catch (Exception e){
        logger.error("Could not update structure element. se = " + se, e);
        return null;
    }
    return databaseElement;
}

现在这个有效。

似乎Spring数据JPA不想像简单的JPA EntityManager那样更新实体....