Search code examples
javaspring-data-jpathymeleaf

Delete from Many to many. How can I remember parameter from URL?


I have 2 tables: Specifications and Parts with many to many relationship. So I create table Spec_Parts for this relationship. In my project I use Thymeleaf and Spring Data JPA. I have button "All specifications" that give me a page with list of all Specifications. All specifications consist of "Parts". So near with every specification I have button "View parts" that open the page with list of "Parts" of current "Specification".

<div align="center">
  <table border="1">
    <tr>
      <th>id</th>
      <th>name</th>
      <th>Exporter</th>
      <th>Type</th>
      <th>Description</th>
    </tr>
    <tr th:each="part : ${parts}">
      <td th:utext="${part.getId()}">...</td>
      <td th:utext="${part.getName()}">...</td>
      <td th:utext="${part.getExportJpa().getName()}">...</td>
      <td th:utext="${part.getTypesJpa().getName()}">...</td>
      <td th:utext="${part.getDescription()}">...</td>
      <td>
        <form th:action="@{/deletePartInSpec}" method="post">
          <input type="hidden" name="id" th:value="${part.id}" />
          <input type="submit" value="Delete" class="btn btn-danger" />
        </form>
      </td>
    </tr>
  </table>
</div>

URL:

http://localhost:8080/allParts?id=1

Where id=1 means first "SPecification" Now I try to create button "Delete", but I don't know how can I remember id of current "Specification" and send it to controller. So how can I delete some "Parts" from "Specifications"?

Parts:

@Entity
@Table(name = "PARTS")
public class PartsJpa {
    @Id
    private int id;
    @Column(name = "NAME")
    private String name;
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "ID_EXPORT", unique = false, nullable = false, updatable = true)
    private ExportJpa exportJpa;
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "ID_TYPE", unique = false, nullable = false, updatable = true)
    private TypesJpa typesJpa;

    @Column(name = "DESCRIPTION")
    private String description;

    @ManyToMany(fetch = FetchType.EAGER)
    private Set<SpecJpa> specJpa; 

Specifications:

@Entity
@Table(name = "SPEC")
public class SpecJpa {
    @Id
    private int id;
    @Column(name = "NAME")
    private String name;
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "Creator_ID", unique = false, nullable = false, updatable = true)
    private UsersJpa usersJpa;
    @Column(name = "DESCRIPTION")
    private String description;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name="SPEC_PARTS",
            joinColumns = @JoinColumn(name="ID_PARTS", referencedColumnName="id"),
            inverseJoinColumns = @JoinColumn(name="ID_SPEC", referencedColumnName="id")
    )
    private Set<PartsJpa> partsJpa;

Solution

  • In your parts controller, you already have the specification id (allParts?id=1), you should add that to the model as as well.

    model.add("specificationId", /* specification id from url */ );
    

    Then, in your form you pass both ids.

    <form th:action="@{/deletePartInSpec}" method="post">
      <input type="hidden" name="spec_id" th:value="${specificationId}" />
      <input type="hidden" name="part_id" th:value="${part.id}" />
      <input type="submit" value="Delete" class="btn btn-danger" />
    </form>
    

    You should be able to delete that relationship based on those two ids.