[SPRING] ตรวจสอบข้อมูลก่อน Save ด้วย hibernate validator ครับ

หลังจาก Blog ตอนที่แล้วผมได้ลองทำ CRUD โดยใช้ Spring Boot ในเรื่องการการจัดการข้อมูล Person ไปแล้วนะครับ แต่ Blog ตอนล่าสุดของผมยังทิ้งท้ายอยู่นะครับ ว่ามันควรจะมีเรื่องของการ Validate ข้อมูลครับ คราวนี้ ผมเขียนตัว Validate ให้มันสมบูรณ์ครับ ซึ่ง Package ที่ผมใช้ hibernate validator ซึ่งเข้าตัวนี้มันเข้ามากับตอนที่เราใส่ Dependency Spring JPA แล้วครับ มาทำเลยดีกว่า

สิ่งที่ต้องมี

  • สร้างเว็บของตัวเองที่มี CRUD กันก่อนครับ
  • หรือ ของผมใช้จาก Blog ตอนที่แล้วครับ

มาลุยกันเลยครับ

  • ชั้น Entity ที่เก็บ POJO Class - ตัว Data Class ของเราแหละครับ เตรียม Annotation ที่เกี่ยวกับการ Validate ข้อมูลครับ อย่างตอนนี้ผมใช้ตัว @NotNull  กับ @Size  ครับ
    @Entity
    public class Person
    {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Integer id;
    
        @NotNull
        @Size(min=3, max=30)	
        private String Firstname;
    
        @NotNull
        @Size(min=3, max=50)	
        private String Lastname;
       
        //มีพวก setter กับ getter อันนี้จะขอละไว้ครับ
    }
  • ชั้น Controller สำหรับ Parameter ต้องการ Validate ข้อมูลนั้น
    • ใช้ Annotation @Valid  ที่อยู่ใน Pacakge javax.validation  เติมนำหน้า Parameter ของ Function ครับ
    • เพิ่ม BindingResult  สำหรับเก็บผลการ Validate ไว้ครับ โดยเก็บไว้ในตัวแปรชื่อ result
    • จากนั้นเติมเงื่อนไขดักการ Validate ข้อมูลครับ โดยใช้ result.hasErrors()  ครับ
      if(result.hasErrors()) {
         //ถ้ามี Error ไม่ยอมให้ Save ต่อ
         return "person/editPerson";
      }
    • มาดู Code สมบูรณ์ของ Method savePerson() ครับ
      @RequestMapping(value = "person", method = RequestMethod.POST)
      public String savePerson(@Valid Person person, BindingResult result) {
         //ดัก Error ไว้ก่อน Insert
         if(result.hasErrors()) {
            return "person/editPerson";
         }
         personService.savePerson(person);
         return "redirect:/persons";
      }
  • ชั้น View อันนี้ตัว Thymeleaf ได้มีตัวช่วยแล้วครับ โดยถ้ามี Error มันถูก Inject เข้ามาในตัวแปร #fields ครับ
    • แสดง Error โดยดูจาก Property hasErrors('ชื่อ Property ใน Enrity[POJO Class])  เช่น ${#fields.hasErrors('Firstname')  ครับ เวลาใช้งานก็ดัก Error ที่ส่งมาจาก Controller ผ่าน th:if  แล้วค่อยแสดงผลครับ Code ตามนี้ครับ
      <div class="form-group">
         <label class="col-sm-2 control-label">Firstname:</label>
         <div class="col-sm-10">
            <input type="text" class="form-control" th:field="*{Firstname}"/>
            <label th:if="${#fields.hasErrors('Firstname')}" th:class="'error'">Firstname Error</label>
         </div>
      </div>
    • มาดู Code ที่ผมได้แก้ไขในไฟล์ editPerson.html  ครับ ใช้ได้ทั้ง Model New / Edit ครับ
      <!DOCTYPE html>
      <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" 
            layout:decorator="layouts/mainLayout">
      
      <head>
          <title>Layout</title>
      </head>
      <body>
          <div layout:fragment="content">
              <h2>Person Details</h2>
              <div>
                  <form class="form-horizontal" th:object="${person}" th:action="@{/person}" method="post">
                      <input type="hidden" th:field="*{id}"/>
                      <!-- <input type="hidden" th:field="*{version}"/> -->
                      <div class="form-group">
                          <label class="col-sm-2 control-label">Firstname:</label>
                          <div class="col-sm-10">
                              <input type="text" class="form-control" th:field="*{Firstname}"/>
                              <label th:if="${#fields.hasErrors('Firstname')}" th:class="'error'">Firstname Error</label>
                          </div>
                      </div>
                      <div class="form-group">
                          <label class="col-sm-2 control-label">Lastname:</label>
                          <div class="col-sm-10">
                              <input type="text" class="form-control" th:field="*{Lastname}"/>
                              <label th:if="${#fields.hasErrors('Lastname')}" th:class="'error'">Lastname Error</label>
                          </div>
                      </div>
                      <div class="form-group">
                          <button type="submit" class="btn btn-default">Submit</button>
                      </div>
                  </form>
              </div>
          </div>
      </body>
      </html>

ลองมาทดสอบกันดูครับ

  • เมื่อมี Error ระบบแสดง Message ดังนี้ครับ

สำหรับ Blog หน้า ผมคงลอง Custom Error Message ดูครับ 😀 แต่ถึงแม้ว่าชั้น Entiry และ Controller มีกลไกในการดัก Validate ข้อมูลแล้ว แต่ฝั่ง Front-End ต้องดักด้วยนะครับ


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts to your email.