Skip to content

Code Snippets

Reusable patterns I keep pasting into new projects — MyBatis dynamic SQL, idempotency, Thymeleaf fragments.

MyBatis Dynamic Search with <where>

MyBatisSQL

<where> only inserts WHERE if at least one <if> matched, and strips a leading AND/OR automatically — so you never hand-manage the boolean edge case of zero active filters.

xml
<select id="searchUsers" resultMap="UserMap">
  SELECT * FROM users
  <where>
    <if test="username != null and username != ''">
      AND username = #{username}
    </if>
    <if test="status != null">
      AND status = #{status}
    </if>
  </where>
</select>

MyBatis Batch Insert with <foreach>

MyBatisSQLPerformance

One round trip instead of N. Keep IN-lists under ~100 items with this pattern — beyond that, a temp-table JOIN is usually faster.

xml
<insert id="batchInsert">
  INSERT INTO users (username, email, status) VALUES
  <foreach collection="users" item="user" separator=",">
    (#{user.username}, #{user.email}, #{user.status})
  </foreach>
</insert>

MyBatis Partial Update with <set>

MyBatisSQL

<set> strips the trailing comma automatically, so an update with only one changed field doesn't fail to compile with a dangling comma.

xml
<update id="dynamicUpdate">
  UPDATE users
  <set>
    <if test="username != null and username != ''">username = #{username},</if>
    <if test="email != null and email != ''">email = #{email},</if>
    <if test="status != null">status = #{status},</if>
  </set>
  WHERE id = #{id}
</update>

Idempotent Payment Endpoint

Spring BootArchitecturePostgreSQL

The exists() check is a fast path for the common case; the UNIQUE constraint on external_tx_id is the actual guarantee, because it closes the TOCTOU race between two near-simultaneous retries.

java
@PostMapping("/pay/auto")
public Response autoPay(@RequestBody AutoPayRequest req) {
    // 1. fast path: check the external transaction id first
    if (paymentService.existsByExternalTxId(req.getExternalTxId())) {
        return Response.duplicate(req.getExternalTxId());
    }
    // 2. UNIQUE constraint + INSERT closes the race window
    //    catch the constraint violation and return the existing result
    return paymentService.processWithIdempotency(req);
}

Thymeleaf Reusable Fragment

Spring BootThymeleaf

th:fragment + th:replace is the decorator pattern for shared UI (navbar, footer) — define once, include everywhere, no copy-pasted markup drifting out of sync.

html
<!-- footer.html -->
<footer th:fragment="copy"> &copy; 2026 dev-notes </footer>

<!-- main.html -->
<div th:replace="~{footer :: copy}"></div>

Safe TO_CHAR on a varchar date column

PostgreSQLSQL

PostgreSQL has no TO_CHAR(varchar, text) overload — code that compiled fine in Oracle fails at runtime here. Cast through TO_DATE first.

sql
-- fails at runtime if REG_DT is varchar 'YYYYMMDD'
-- TO_CHAR(REG_DT, 'YYYY.MM.DD')

-- varchar -> date -> formatted text
SELECT TO_CHAR(TO_DATE(REG_DT, 'YYYYMMDD'), 'YYYY.MM.DD')
FROM users;

JWT Auth Token Filter (Spring Security)

Spring BootSecurityJWT

Runs once per request via OncePerRequestFilter. If the token is missing or fails validateJwtToken(), it silently falls through — no exception, no authentication set — leaving the request unauthenticated for downstream checks to reject.

java
public class AuthTokenFilter extends OncePerRequestFilter {

    @Autowired private JwtUtils jwtUtils;
    @Autowired private UserService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                     FilterChain filterChain) throws ServletException, IOException {
        try {
            String jwt = parseJwt(request);
            if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
                String username = jwtUtils.getUserNameFromJwtToken(jwt);
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception e) {
            logger.error("Cannot set user authentication: {}", e);
        }
        filterChain.doFilter(request, response);
    }

    private String parseJwt(HttpServletRequest request) {
        String headerAuth = request.getHeader("Authorization");
        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
            return headerAuth.substring(7);
        }
        return null;
    }
}

MapStruct DTO Mapper (Compile-Time)

Spring BootREST APIMapStruct

A mismatched field name here is a compile error, not a silent runtime null — that's the main reason to prefer MapStruct over reflection-based mappers for anything beyond a quick prototype.

java
@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    @Mapping(source = "email", target = "emailAddress")
    @Mapping(source = "name", target = "fullName")
    UserDTO toUserDTO(UserApp userApp);
}

Centralized Exception Handler with ProblemDetail

Spring BootREST APIError Handling

@ControllerAdvice centralizes error formatting across every controller. ProblemDetail implements RFC 7807 (application/problem+json) so the frontend gets one standard error shape instead of guessing a custom schema per endpoint.

java
public class StudentNotFoundException extends RuntimeException {
    public StudentNotFoundException(String message) { super(message); }
}

@ControllerAdvice
public class CustomizedExceptionHandling {

    @ExceptionHandler(StudentNotFoundException.class)
    ProblemDetail handleExceptions(StudentNotFoundException exception, WebRequest webRequest) {
        ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(
            HttpStatus.NOT_FOUND, exception.getMessage());
        problemDetail.setTitle("Not Found!");
        return problemDetail;
    }
}

Constructor Injection (No @Autowired Needed)

Spring BootArchitecture

Spring's own recommendation: constructor injection for mandatory dependencies. The dependency list is visible in the signature, the object can't exist half-initialized, and it's trivial to unit test without a Spring context.

java
@Component
public class Car {
    private final Person person;

    public Car(Person person) {
        this.person = person;
    }

    public void drive() {
        person.sayHello();
    }
}

2NF Table Split (Composite Key → Three Tables)

PostgreSQLSQLDatabase

A composite primary key (student_id, subject_id) with student_name depending only on student_id is a partial dependency — the classic 2NF violation. Splitting into three tables removes it.

sql
create table student (
  student_id int primary key,
  student_name text,
  country_code text,
  country text
);

create table subject (
  subject_id int primary key,
  subject text
);

create table student_subject (
  student_id int references student(student_id),
  subject_id int references subject(subject_id),
  scores int,
  primary key (student_id, subject_id)
);

PL/pgSQL: IF, CASE, and LOOP in One Block

PostgreSQLPL/pgSQL

The three control-flow shapes that cover almost every anonymous PL/pgSQL block: conditional branching, exact-value matching, and a manually-bounded loop.

sql
DO $$
DECLARE
  a INTEGER := 10;
  count INTEGER := 0;
BEGIN
  IF a > 5 THEN
    RAISE NOTICE 'a is greater than five';
  END IF;

  CASE a
    WHEN 10 THEN RAISE NOTICE 'a is exactly ten';
    ELSE RAISE NOTICE 'a is something else';
  END CASE;

  LOOP
    EXIT WHEN count >= 3;
    RAISE NOTICE 'count = %', count;
    count := count + 1;
  END LOOP;
END $$;

Conventional Commit Message Format

GitConventions

One prefix makes a commit self-describing and lets tooling generate changelogs directly from git history instead of someone writing them by hand.

text
<type>: <short summary>

feat: add idempotency check to auto-pay endpoint
fix: null pointer on empty cart at checkout
refactor: extract JWT parsing into JwtUtils
docs: add MyBatis dynamic SQL examples to README
chore: bump spring-boot-starter-security to 3.2.1