闽公网安备 35020302035485号
前言
在一次Java后端开发的面试中,面试官问了我一个问题:“你在写代码时会复用公共SQL吗?如果会的话,能详细介绍一下你是如何实现的吗?”这个问题让我眼前一亮,因为在实际项目中,SQL复用确实是一个非常实用且能提升代码质量的做法。下面是我当时的回答,也借此机会整理成一篇博客,和大家分享一下我的经验。
<!-- 定义公共SQL片段 -->
<sql id="userBaseColumns">
id, username, email, created_at, updated_at
</sql>
<!-- 堆代码 duidaima.com -->
<!-- 查询用户列表 -->
<select id="selectUserList" resultType="User">
SELECT <include refid="userBaseColumns"/>
FROM users
WHERE status = #{status}
</select>
<!-- 查询单个用户 -->
<select id="selectUserById" resultType="User">
SELECT <include refid="userBaseColumns"/>
FROM users
WHERE id = #{id}
</select>
通过 <include> 标签,我可以在多个SQL语句中复用 userBaseColumns 这个片段。这样,如果以后需要调整查询字段(比如新增 phone 字段),只需要改动 <sql> 定义的地方,所有引用它的查询都会自动更新,省时省力。public class PageHelper {
public static String appendPageSql(String sql, int pageNum, int pageSize) {
int offset = (pageNum - 1) * pageSize;
return sql + " LIMIT " + pageSize + " OFFSET " + offset;
}
}
然后在Mapper接口中调用:@SelectProvider(type = UserSqlProvider.class, method = "getUserListSql")
List<User> getUserList(int status, int pageNum, int pageSize);
class UserSqlProvider {
public String getUserListSql(int status, int pageNum, int pageSize) {
String sql = "SELECT id, username, email FROM users WHERE status = #{status}";
return PageHelper.appendPageSql(sql, pageNum, pageSize);
}
}
这样,任何需要分页的查询都可以复用 PageHelper ,只需要传入页码和每页大小即可。这种方式在Java层实现了SQL的动态拼接,既灵活又可控。public class SqlConstants {
public static final String USER_BASE_COLUMNS = "id, username, email, created_at, updated_at";
public static final String USER_TABLE = "users";
public static final String SELECT_USER_BY_ID =
"SELECT " + USER_BASE_COLUMNS + " FROM " + USER_TABLE + " WHERE id = ?";
}
然后在DAO层使用:public User getUserById(Long id) {
String sql = SqlConstants.SELECT_USER_BY_ID;
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new UserRowMapper());
}
这种方式的好处是简单直观,适合小型项目或者需要快速开发的场景。不过缺点是缺乏动态性,如果SQL逻辑复杂,维护起来会稍显麻烦。