2015-05-26 35 views
1

我有兩個實體EnvironnmentServeurApplicatif有一對多關係。每當用戶想要將一個ServeurApplicatif關聯到Environnement實體上時,我都有一個帶有按鈕的動態表單,以便添加一個新表單。提交期望結果時,環境實體和與之關聯的ServeurApplicatif實體都將持久化。Spring MVC - 提交表單時丟失了子實體ID

但是在我的情況下,我得到一個400 http錯誤:您的請求是合成不正確的,無論何時我嘗試提交表單。

這裏是JavaScript代碼動態地將孩子實體相關的形式:

<script type="text/javascript"> 
$(document).ready(function() { 

    var index = ${fn:length(env.serveurApplicatifs)}; 
    console.log("index value :"+index); 
    $("#addServ").off("click").on("click",function() { 
     $(this).before(function() { 

     var html = '<div id="serveurApplicatifs'+index+'.wrapper" style="display: none;">'; 
     html += '<input type="hidden" id="serveurApplicatifs'+index+'.idserv" name="serveurApplicatifs['+index+'].idserv" ></input>';      
       html += '<p><strong>Serveur Applicatif 1 : </strong></p>'; 
       html += '<div class="form-group"><label for="serveurApplicatifs'+index+'.port">Port :</label><input class ="form-control" type="text" id="serveurApplicatifs'+index+'.port" name="serveurApplicatifs['+index+'].port" ></input></div>'; 
       html += '<div class="form-group"><label for="serveurApplicatifs'+index+'.compte">Compte :</label><input class ="form-control" type="text" id="serveurApplicatifs'+index+'.compte" name="serveurApplicatifs['+index+'].compte" ></input></div>'; 
       html += '<div class="form-group"><label for="serveurApplicatifs'+index+'.pwd">Mot de passe :</label><input class ="form-control" type="text" id="serveurApplicatifs'+index+'.pwd" name="serveurApplicatifs['+index+'].pwd" ></input></div>'; 
       html += '<div class="form-group"><label for="serveurApplicatifs'+index+'.adresse">Adresse :</label><input class ="form-control" type="text" id="serveurApplicatifs'+index+'.adresse" name="serveurApplicatifs['+index+'].adresse" ></input></div>'; 
       html += '<a href="#" class="serveurApplicatifs.remove" data-index="'+index+'">Supprimer</a>';      
       html += "</div>"; 
       return html; 
      }); 
     $("#serveurApplicatifs"+index+"\\.wrapper").show(); 
     index++; 
      return false; 
     }); 

     $("a.serveurApplicatifs.remove").off("click").on("click",function() { 
      var index2remove = $(this).data("index"); 
      $("#serveurApplicatifs"+index2remove+"\\.wrapper").hide(); 
      $("#serveurApplicatifs"+index2remove+"\\.remove").val("1"); 
      return false; 
      }) 

JSP中的Spring表單標籤:

<c:url value="/envs/save" var="saveUrl"/> 
    <form:form action="${ saveUrl }" method="POST" modelAttribute="env"> 
     <div class="form-group"> 
     <form:input type="hidden" class="form-control" id="idEnv" placeholder="id" path="idEnv"></form:input><span id="star">*</span> 
    </div> 
    <!-- ------------- --> 
    <div class="form-group"> 
     <label for="nom">Nom</label> 
     <form:input type="text" class="form-control" id="nom" placeholder="Nom" path="nom"></form:input><span>*</span> 
     <form:errors path="nom" cssClass="error"></form:errors> 
    </div> 
    <div class="form-group"> 
     <label for="plateforme">Platforme</label> 
     <form:input type="text" class="form-control" id="plateform" placeholder="Plateforme" path="platforme"></form:input> 
    <form:errors path="platforme" cssClass="error"></form:errors> 
    </div> 
    <div class="form-group"> 
     <label for="typologie">Typologie</label> 
     <form:input type="text" class="form-control" id="typologie" placeholder="Typologie" path="typologie"></form:input> 
     <form:errors path="typologie" cssClass="error"></form:errors> 

    </div> 
    <div class="form-group"> 
     <label for="bd">Base de donnée</label> 
     <form:input type="text" class="form-control" id="bd" placeholder="Bdd" path="bd"></form:input> 
     <form:errors path="bd" cssClass="error"></form:errors> 
    </div> 

    <div class="form-group"> 
     <label for="version">Version</label> 
     <form:input type="text" class="form-control" id="version" placeholder="Version" path="version"></form:input> 
     <form:errors path="version" cssClass="error"></form:errors> 

    </div> 
    <div class="form-group"> 
     <label for="machine_bd">Serveur de base de données</label> 
     <form:input type="text" class="form-control" id="machine_bd" placeholder="Machine Bdd" path="machineBd"></form:input> 
     <form:errors path="machineBd" cssClass="error"></form:errors> 

    </div> 
    <div class="form-group"> 
     <label for="port_bd">Port Base de données</label> 
     <form:input type="text" class="form-control" id="port_bd" placeholder="Port bdd" path="portBd"></form:input> 
     <form:errors path="portBd" cssClass="error"></form:errors> 

    </div> 
    <div class="form-group"> 
     <label for="version_bd">Version de base de données</label> 
     <form:input type="text" class="form-control" id="version_bd" placeholder="Version bdd" path="versionBd"></form:input> 
     <form:errors path="versionBd" cssClass="error"></form:errors> 

    </div> 
    <div class="form-group"> 
     <label for="type_bd">Type de base de données</label> 
     <form:input type="text" class="form-control" id="type_bd" placeholder="Type bdd" path="typeBd"></form:input> 
     <form:errors path="typeBd" cssClass="error"></form:errors> 

    </div> 
<div class="form-group"> 
     <label for="depart">Environnement de départ</label> 
     <form:radiobutton value ="1" id="depart" path="depart" label="Oui"></form:radiobutton> 
     <form:radiobutton value ="0" id="depart" path="depart" label="Non"></form:radiobutton> 
     <form:errors path="depart" cssClass="error"></form:errors> 

    </div> 
    <div class="form-group"> 
     <label for="repert">Repert</label> 
     <form:input type="text" class="form-control" id="repert" placeholder="Repert" path="repert"></form:input> 
     <form:errors path="repert" cssClass="error"></form:errors> 

    </div> 
    <div class="form-group"> 
     <label for="port_ftp">Port FTP</label> 
     <form:input type="text" class="form-control" id="port_ftp" placeholder="Port FTP" path="portFtp"></form:input> 
     <form:errors path="portFtp" cssClass="error"></form:errors> 

    </div> 
    <div class="form-group"> 
     <label for="exclu">Exclu</label> 
     <form:radiobutton value ="1" id="exclu" path="exclu" label="Oui"></form:radiobutton> 
     <form:radiobutton value ="0" id="exclu" path="exclu" label="Non"></form:radiobutton> 
     <form:errors path="exclu" cssClass="error"></form:errors> 

    </div> 
    <div class="form-group"> 
     <label for="envsPrec">Précedent</label> 
     <form:select class="form-control" id="envsPrec" path="environnements2" items="${ envsPrecSuiv }" itemLabel="nom" itemValue="idEnv"/> 
     <form:errors path="environnements2" cssClass="error"></form:errors> 
    </div> 
    <div class="form-group"> 
     <label for="envsSuiv">Suivant</label> 
     <form:select class="form-control" id="envsSuiv" path="environnements1" items="${ envsPrecSuiv }" itemLabel="nom" itemValue="idEnv"/> 
     <form:errors path="environnements1" cssClass="error"></form:errors> 
    </div> 
    <c:forEach varStatus="loop" var="serveurApplicatifs" items="${ env.serveurApplicatifs }"> 
     <c:choose> 
     <c:when test="${env.serveurApplicatifs[loop.index].remove eq 1 }"> 
      <div id="serveurApplicatifs${loop.index }.wrapper" style="display: none;"> 
     </c:when> 
     <c:otherwise> 
      <div id="serveurApplicatifs${ loop.index }.wrapper"> 
     </c:otherwise> 
     </c:choose> 
     <div class="form-group"> 
      <form:input type="hidden" class="form-control" id="idApp" path="env.serveurApplicatifs[${loop.index}].idserv"></form:input> 
     </div> 
     <div class="form-group"> 
      <label for="portApp">Port serveur applicatif</label> 
      <form:input type="text" class="form-control" id="portApp" placeholder="Port" path="env.serveurApplicatifs[${loop.index}].port"></form:input> 
     </div> 
     <div class="form-group"> 
      <label for="compteApp">Compte serveur applicatif</label> 
      <form:input type="text" class="form-control" id="compteApp" placeholder="Compte" path="env.serveurApplicatifs[${loop.index}].compte"></form:input> 
     </div> 
     <div class="form-group"> 
      <label for="pwdApp">Mot de passe serveur applicatif</label> 
      <form:input type="text" class="form-control" id="pwdApp" placeholder="Mot de passe" path="env.serveurApplicatifs[${loop.index}].pwd"></form:input> 
     </div> 
     <div class="form-group"> 
      <label for="adresseApp">Adresse serveur applicatif</label> 
      <form:input type="text" class="form-control" id="adresseApp" placeholder="Adresse" path="env.serveurApplicatifs[${loop.index}].adresse"></form:input> 
     </div> 
     <c:choose> 
      <c:when test="${serveurApplicatifs[loop.index].remove eq 1}"><c:set var="hiddenValue" value="1"></c:set></c:when> 
      <c:otherwise><c:set var="hiddenValue" value="0"></c:set> </c:otherwise> 
     </c:choose> 
     <form:hidden path="serveurApplicatifs[${loop.index}].remove" value="${hiddenValue}"/> 
     <a href="#" class="serveurApplicatifs.remove" data-index="${loop.index}">Supprimer</a> 
    </div> 
</c:forEach> 
    <button type="button" class="btn btn-default" id="addServ">Ajouter Un Serveur d'application</button> 
    <button type="submit" class="btn btn-default" value="Save">Submit</button> 

</form:form> 

的環境公司實體類:

@Entity 
@NamedQuery(name="Environnement.findAll", query="SELECT e FROM Environnement e") 
public class Environnement implements Serializable { 
private static final long serialVersionUID = 1L; 

@Id 
@GeneratedValue(strategy=GenerationType.IDENTITY) 
@Column(name="id_env") 
private int idEnv; 

private String bd; 

private int depart; 

private int exclu; 

@Column(name="machine_bd") 
private String machineBd; 

@Column(name="mdp_bdd") 
private String mdpBdd; 

private String nom; 

private String platforme; 

@Column(name="port_bd") 
private int portBd; 

@Column(name="port_ftp") 
private int portFtp; 

private String repert; 

@Column(name="type_bd") 
private String typeBd; 

private String typologie; 

@Column(name="utilisateur_bdd") 
private String utilisateurBdd; 

private String version; 

@Column(name="version_bd") 
private String versionBd; 

//bi-directional many-to-many association to Composant 
@ManyToMany 
@JoinTable(
    name="env_comp" 
    , joinColumns={ 
     @JoinColumn(name="id_env") 
     } 
    , inverseJoinColumns={ 
     @JoinColumn(name="id_comp") 
     } 
    ) 
private List<Composant> composants; 

//bi-directional many-to-many association to Environnement 
@LazyCollection(LazyCollectionOption.FALSE) 
@ManyToMany 
@JoinTable(
    name="lien_environnement" 
    , joinColumns={ 
     @JoinColumn(name="id_env_suiv") 
     } 
    , inverseJoinColumns={ 
     @JoinColumn(name="id_env_prec") 
     } 
    ) 
private List<Environnement> environnements1; 

//bi-directional many-to-many association to Environnement 
@LazyCollection(LazyCollectionOption.FALSE) 
@ManyToMany 
@JoinTable(
     name="lien_environnement" 
     , joinColumns={ 
      @JoinColumn(name="id_env_prec") 
      } 
     , inverseJoinColumns={ 
      @JoinColumn(name="id_env_suiv") 
      } 
     ) 
private List<Environnement> environnements2; 

//bi-directional many-to-one association to ServeurApplicatif 
@LazyCollection(LazyCollectionOption.FALSE) 
@OneToMany(mappedBy="environnement") 
private List<ServeurApplicatif> serveurApplicatifs; 

的ServeurApplicatif實體類:

@Entity 
@Table(name="serveur_applicatif") 
@NamedQuery(name="ServeurApplicatif.findAll", query="SELECT s FROM ServeurApplicatif s") 
public class ServeurApplicatif implements Serializable { 
private static final long serialVersionUID = 1L; 

@Id 
@GeneratedValue(strategy=GenerationType.IDENTITY) 
private int idserv; 

private String adresse; 

private String compte; 

private int port; 

private String pwd; 

@Transient 
private Integer remove; 

//bi-directional many-to-one association to Environnement 
@ManyToOne 
@JoinColumn(name="id_env") 
private Environnement environnement; 

控制器方法用於保存所述實體:

@RequestMapping(value="/envs/save",method=RequestMethod.POST) 
public ModelAndView saveEnvironnement(@ModelAttribute(value="env")Environnement env) { 

    //Environnement envFinal = this.envService.validate(env); 

    this.envService.gererServeur(env); 

    /*for (ServeurApplicatif servApp : env.getServeurApplicatifs()) { 

    }*/ 

    envService.saveOrUpdate(env); 
    for (ServeurApplicatif servApp : env.getServeurApplicatifs()) { 
     servAppService.saveOrUpdate(servApp); 
    } 
    return new ModelAndView("redirect:/envs"); 

} 

gererServeur方法在EnvironnementService CLASSE:

@Override 
public List<ServeurApplicatif> gererServeur(Environnement env) { 
    // TODO Auto-generated method stub 
    List<ServeurApplicatif> serveurRemoved = new ArrayList<ServeurApplicatif>(); 
    if(env.getServeurApplicatifs() != null) { 
     for (Iterator<ServeurApplicatif> iterator = serveurRemoved.iterator(); iterator 
       .hasNext();) { 
      ServeurApplicatif serveurApplicatif = iterator.next(); 
      if(serveurApplicatif.getRemove() == 1) { 
       serveurRemoved.add(serveurApplicatif); 
       iterator.remove(); 
      } 
      else { 
       serveurApplicatif.setEnvironnement(env); 
      } 

     } 
    } 
    return serveurRemoved; 
} 

請注意,我用這裏顯示的解決方案來管理動態形式: Spring 3 MVC: one-to-many within a dynamic form (add/remove on create/update)

編輯:

我嘗試宣告線var index = ${fn:length(env.serveurApplicatifs)};文檔準備功能之外,但它並沒有幫助中,裝載的console.log形式,但是每次我CLIC按鈕以添加新的形式爲ServeurApplicatif被遞增時返回0,發送到服務器表單數據如下:

idEnv:0 
nom: 
platforme: 
typologie: 
bd: 
version: 
machineBd: 
portBd:0 
versionBd: 
typeBd: 
depart:0 
repert: 
portFtp:0 
exclu:0 
_environnements2:1 
_environnements1:1 
serveurApplicatifs[0].idserv: 
serveurApplicatifs[0].port:14523 
serveurApplicatifs[0].compte:test 
serveurApplicatifs[0].pwd:test 
serveurApplicatifs[0].adresse:test 
serveurApplicatifs[1].idserv: 
serveurApplicatifs[1].port:14523 
serveurApplicatifs[1].compte:test 
serveurApplicatifs[1].pwd:test 
serveurApplicatifs[1].adresse:test 
_csrf:2d856fad-16f3-4ae4-a254-47922a695c17 

你會注意到idserv不會像idenv那樣自動填充。這兩個ID都是數據庫中的自動遞增字段,其他空白字段爲空,因此問題不存在。

在此先感謝。

+0

我已經這樣做了,並且發送到服務器的參數看起來是正確的,但ServeurApplicatif ID字段保持空白,並且在提交時不會自動生成,與發送correclty的Environnement id不同。 – Pedro

回答

0

我發現有什麼問題。

基本上被調用saveOrUpdate當idserv沒有得到的0使得 彈簧可以處理請求到服務器和休眠可以插入ServeurApplicatif實體沿着Environnment實體默認值,所以我添加了一個value="0"到JavaScript代碼負責創建表單輸入ServeurApplicatifs在飛行中,現在它按預期工作。