Search code examples
javaspringmicroservicesmybatis

How can I guarantee successful deletion or update without extra request?


In the service layer of some microservice, I make a POST request to another microservice to remove some records from the database:

@Override
public IdsResponse removeSomeStuff(IdsRequest request) throws NotFoundException {
    try {
        POST(SomeStuffEndpoint.createUrl(this.baseUri, REMOVE_SOME_STUFF), request, 
               IdsResponse.class);
    } catch(NotFoundException e) {
        logger.error("...", e);
        throw new NotFoundException(String.format("...: %s", e.getMessage()), e);
    }
    return new IdsResponse();
}

A request comes in, for example, at the end point of the other microservice:

@Path("/some-stuff")
public interface SomeStuffEndpoint {

    @POST
    @Path("/remove")
    Response removeSomeStuff(@Context MessageContext context);

    ...
}

In the DAO layer of this microservice, I delete (or update) records from the database:

public class SomeStuffDaoImpl implements SomeStuffDao {
    private static final Logger logger = LoggerFactory.getLogger(SomeStuffDaoImpl.class);

    @Autowired
    SomeStuffMapper someStuffMapper;

    @Override
    public void removeSomeStuff(List<Long> someIds, List<Long> someAnotherIds) {
        try {
            someStuffMapper.removeSomeStuff(someIds, someAnotherIds);
        } catch (InvocationTargetException | PSQLException | BadSqlGrammarException e) {
            logger.error("...");
        }
    }
    ...
}   

I use MyBatis 3 as persistence framework. The removal is as follows:

<?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="some.company.appname.mservicename.model.mapper.SomeStuffMapper">

    <delete id="removeSomeStuff" parameterType="map">
        delete from some_stuff where some_id in
        <foreach collection="someIds" item="someId" 
                index="index" 
                open="(" separator="," close=")">
            #{someId}
        </foreach>

        and another_stuff in

        <foreach collection="someAnotherIds" item="someAnotherId" 
                 index="index" 
                 open="(" separator="," close=")">
            #{someAnotherId}
        </foreach>
    </delete>
... 

How can I make sure that the removal or update was successful and don't make an additional request for check?

For example, the request contains an incorrect combination of identifiers and records were not found (an exception is not thrown)?


Solution

  • You can return some information as a result of the update/delete. In the simplest case it can be the number of the records affected. This way client would know that no records are deleted for example.

    To do this modify signature of removeSomeStuff in mapper to return int. Mybatis will return the number of affected records. This can be done for any modification operation.

    In some cases it is helpful to return more information about affected records for example the ids of records that were deleted. You haven't specified what RDBMS you are using. In postgres you can convert delete to something like:

    <select id="removeSomeStuff" parameterType="map" resultType="long" flushCache="true">
    
        delete from some_stuff where some_id in
        <foreach collection="someIds" item="someId" 
                index="index" 
                open="(" separator="," close=")">
            #{someId}
        </foreach>
    
        and another_stuff in
    
        <foreach collection="someAnotherIds" item="someAnotherId" 
                 index="index" 
                 open="(" separator="," close=")">
            #{someAnotherId}
        </foreach>
        RETURNING id
    </select>