SQL 負責「怎麼存」,Java 負責「存什麼」。資料庫層不應包含複雜業務規則(長度截取、條件轉換),否則導致 SQL 膨脹、難測試、移植性差。
public interface UserMapper {
@Insert("INSERT INTO t_user(id, code) VALUES(#{id}, #{code})")
void insert(User user);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired UserMapper userMapper;
@Override
@Transactional
public void save(UserDTO dto) {
String raw = dto.getCode(); // 前台傳入字串
String processed = processCode(raw); // 統一處理邏輯
User user = new User();
user.setId(IdGenerator.nextId());
user.setCode(processed);
userMapper.insert(user);
}
private String processCode(String raw) {
if (raw == null) return null;
if (raw.length() > 9) return raw.substring(0, 9); // 截取前 9 位
if (raw.length() < 9) return null; // 不足 9 位存空值
return raw;
}
}
<if> / substring?| 缺點 | 說明 |
|---|---|
| SQL 可讀性下降 | 業務邏輯分散在 XML 片段,難以整體審視 |
| 單元測試困難 | 需啟動資料庫才能驗證截取邏輯 |
| 資料庫耦合 | Oracle SUBSTR、MySQL SUBSTRING、PG SUBSTRING 語法不一 |
| 效能誤區 | 以為資料庫處理快,實則網路傳輸原始長字串更佔頻寬 |
<insert id="insertRaw" parameterType="string">
INSERT INTO t_table(code)
VALUES (
<choose>
<when test="_parameter != null and _parameter.length() > 9">
#{_parameter.substring(0, 9)}
</when>
<when test="_parameter != null and _parameter.length() < 9">
NULL
</when>
<otherwise>
#{_parameter}
</otherwise>
</choose>
)
</insert>
⚠️ 僅限**無業務邏輯、純資料清洗/遷移**場景,嚴禁用於核心業務流程。
**長度截取、條件轉空值等屬於業務規則,請在 Java Service 層完成**。MyBatis XML 只做參數綁定與簡單動態拼接(如 where、set、foreach),保持 SQL 純粹、可測試、可移植。