Code Snippets
Reusable patterns I keep pasting into new projects — MyBatis dynamic SQL, idempotency, Thymeleaf fragments.
MyBatis Dynamic Search with <where>
<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.
<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>
One round trip instead of N. Keep IN-lists under ~100 items with this pattern — beyond that, a temp-table JOIN is usually faster.
<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>
<set> strips the trailing comma automatically, so an update with only one changed field doesn't fail to compile with a dangling comma.
<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
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.
@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
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.
<!-- footer.html -->
<footer th:fragment="copy"> © 2026 dev-notes </footer>
<!-- main.html -->
<div th:replace="~{footer :: copy}"></div>Safe TO_CHAR on a varchar date column
PostgreSQL has no TO_CHAR(varchar, text) overload — code that compiled fine in Oracle fails at runtime here. Cast through TO_DATE first.
-- 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)
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.
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)
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.
@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
@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.
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'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.
@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)
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.
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
The three control-flow shapes that cover almost every anonymous PL/pgSQL block: conditional branching, exact-value matching, and a manually-bounded loop.
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
One prefix makes a commit self-describing and lets tooling generate changelogs directly from git history instead of someone writing them by hand.
<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