javaspringhttpmybatishttp-verbs

how to implement http patch logic


i am using java, spring mvc and mybatis.

for http patch, it is used to update partial resource, while put updates the entirely resource.

my code looks like

@RestController
@RequestMapping("/test")
public class Test {
@PutMapping
public void update(MyBean myBean) {
    //update MyBean
}

mybatis code is:

<update id="updateMyBean">
    update My_Bean
    <set>
        <if test="filed1 != null>field1 = #{field1},</if>
        <if test="filed2 != null>field1 = #{field2},</if>
        <if test="filed3 != null>field1 = #{field3},</if>
    </set>
    where id = #{id}
</update>

then how to implement patch in the spring mvc? how to implement patch in mybatis?

is it add another update method like following?

@PutMapping
public void update(MyBean myBean) {
    //update MyBean
}

@PatchMapping
public void updateBeanPartial(MyBean myBean) {
    //update MyBean
}
//they look like the same just annotations and/or method name are different
or
@PatchMapping
public void updateBeanPartial(Map myBeanMap) {
    //update MyBean
}
//use Map as parameters, but in this case, we cannot do bean validation easily and cannot show what fields need to be sent in swagger

//or use specified fields of MyBean as parameter, but it will introduce many controller methods because MyBean can have many fields

and they use same mybatis update statement?

Thus, how to implement put and patch in the code? or their difference only in the semantic not in the code?


Solution

  • Lets clarify some things first:

    In your Batis mapper XML, would you need to define 2 functions:

    Update User , Patch User ,

    What you define in your batis mapper is your DAO statements.

    What you define your Spring MVC is your Controller/Services, and what you want to achieve.

    If you want 2 endpoints (PUT, PATCH), and you want them to do different things, then you need 2 different statements in batis.

    Take note of <mapper namespace="org.com.BatisUserService"> which is what you will use to later on reference the implementations from your other classes such as @Controller, or @Service in your Spring MVC app.

    <?xml version="1.0" encoding="UTF-8" ?>    
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="org.com.BatisUserService">  <---- Take note of this
        <update id="updateUser"
            parameterType="org.com.model.User">
            UPDATE user SET
            user_name=#{userName,jdbcType=VARCHAR},
            user_password=#{userPassword,jdbcType=VARCHAR},
            user_email=#{userEmail,jdbcType=VARCHAR}
            WHERE
            user_id=#{userId,jdbcType=INTEGER};
        </update>
    
        <update id="patchUser"
            parameterType="org.com.model.User">
            UPDATE user SET
            user_name=#{userName,jdbcType=VARCHAR}
            user_password=#{userPassword,jdbcType=VARCHAR},
            WHERE
            user_id=#{userId,jdbcType=INTEGER};
        </update>
    </mapper>
    

    Then in your Controller, you would then call your Mapper org.com.BatisUserService which has the functions updateUser and patchUser defined:

    @Controller
    @RequestMapping(value = "/user")
    public class UserController {
    
      @Autowired
      private BatisUserService batisUserService;
    
      @RequestMapping(value = "/updateUser", method = RequestMethod.POST)
      public User updateUser(User user) {
          batisUserService.updateUser(user);
      }
    
      @RequestMapping(value = "/patchUser", method = RequestMethod.PATCH)
      public User patchUser(User user) {
          batisUserService.patchUser(user);
      }
    
    }