Encrypting Sensitive Data in MySQL with MyBatis TypeHandler – A Step‑by‑Step Guide

This article explains why storing plain‑text sensitive fields such as phone numbers is unsafe, then demonstrates how to use a custom MyBatis TypeHandler to automatically encrypt data on insert and decrypt it on query, complete with code samples, configuration steps, and test results.

Top Architect
Top Architect
Top Architect
Encrypting Sensitive Data in MySQL with MyBatis TypeHandler – A Step‑by‑Step Guide

Background

In many databases, sensitive user information like phone numbers or bank cards is sometimes stored in plain text, which can be leaked if the database is compromised or data is exported by a departing employee.

Solution

Because the project uses MyBatis as the persistence layer, a custom TypeHandler is chosen to handle encryption and decryption of specific columns.

Implementation Steps

Define an entity class for encrypted values

public class Encrypt {
    private String value;
    public Encrypt() {}
    public Encrypt(String value) { this.value = value; }
    public String getValue() { return value; }
    public void setValue(String value) { this.value = value; }
}

Implement the TypeHandler

@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(Encrypt.class)
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt> {
    private static final byte[] KEYS = "12345678abcdefgh".getBytes(StandardCharsets.UTF_8);
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Encrypt parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null || parameter.getValue() == null) {
            ps.setString(i, null);
            return;
        }
        AES aes = SecureUtil.aes(KEYS);
        String encrypt = aes.encryptHex(parameter.getValue());
        ps.setString(i, encrypt);
    }
    @Override
    public Encrypt getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return decrypt(rs.getString(columnName));
    }
    @Override
    public Encrypt getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return decrypt(rs.getString(columnIndex));
    }
    @Override
    public Encrypt getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return decrypt(cs.getString(columnIndex));
    }
    private Encrypt decrypt(String value) {
        if (value == null) return null;
        return new Encrypt(SecureUtil.aes(KEYS).decryptStr(value));
    }
}

Mapper XML configuration

<?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="com.huan.study.mybatis.mappers.CustomerMapper">
    <resultMap id="BaseResultMapper" type="com.huan.study.mybatis.entity.Customer">
        <id column="id" property="id"/>
        <result column="phone" property="phone"/>
        <result column="address" property="address"/>
    </resultMap>
    <insert id="addCustomer">
        INSERT INTO customer(phone, address) VALUES (#{phone}, #{address})
    </insert>
    <select id="findCustomer" resultMap="BaseResultMapper">
        SELECT * FROM customer WHERE phone = #{phone}
    </select>
</mapper>

MyBatis configuration

mybatis.type-handlers-package = com.huan.study.mybatis.typehandler

Service layer Provide methods to add a customer (the phone field is wrapped in Encrypt so it gets encrypted) and to query a customer by phone (the result is automatically decrypted).

Testing Results

After inserting a record, the phone column in the database contains an encrypted string. When querying the same record, MyBatis invokes the TypeHandler to decrypt the value, returning the original phone number.

Below are screenshots of the mapper XML and the test output confirming the encryption/decryption behavior.

Mapper XML screenshot
Mapper XML screenshot
Test result screenshot
Test result screenshot
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSQLBackend DevelopmentMyBatisdata encryptionTypeHandler
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.