<delete id="deleteByEntity" parameterType="com.javapandeng.po.Manage">delete from manage where 1=1<include refid="Manage_where"/></delete>
//在这个代码中,manage只是一个实体类,为什么可以通过它删除
这是一个非常好的问题,它触及了 MyBatis 动态 SQL 的一个核心技巧。虽然 Manage
是一个实体类,但这段代码巧妙地利用了它来构建一个灵活的条件删除语句。
关键就在于 <include refid="Manage_where"/>
所引用的 Manage_where
SQL 片段。这个片段内部使用了 MyBatis 的动态 SQL 标签(如 <if>
)。
核心原理:动态 SQL
MyBatis 的强大之处在于它的动态 SQL 能力。它允许你在 XML 中编写“智能”的 SQL 片段,这些片段会根据传入参数的具体值来动态地改变最终生成的 SQL 语句。
Manage_where
片段(虽然没有在你提供的代码中展示,但这是标准做法)通常会像下面这样定义:
<!-- 这是一个假设的 Manage_where 片段定义 -->
<sql id="Manage_where"><if test="id != null">AND id = #{id}</if><if test="userName != null and userName != ''">AND userName = #{userName}</if><if test="passWord != null and passWord != ''">AND passWord = #{passWord}</if><if test="realName != null and realName != ''">AND realName = #{realName}</if>
</sql>
工作流程详解
现在,我们把 deleteByEntity
语句和 Manage_where
片段结合起来看:
-
你调用 Mapper 方法:
// 假设有一个 Manage 对象,你只设置了 id
Manage condition = new Manage();
condition.setId(5);
// 调用删除方法
manageMapper.deleteByEntity(condition);
-
MyBatis 接收参数对象:它接收到一个 Manage
类型的对象作为参数。这个对象就是你的“条件实体”,它的非空属性就代表了删除的筛选条件。
-
构建 SQL 语句:
-
MyBatis 从 delete from manage where 1=1
开始。
-
然后它引入(include) Manage_where
片段。
-
在 Manage_where
片段内部,MyBatis 会检查传入的 manage
对象的每一个属性:
-
test="id != null"
:检查 condition.getId()
是否不为 null。因为是 5
,条件为真,所以追加 AND id = #{id}
。
-
test="userName != null and userName != ''"
:检查 condition.getUserName()
。我们没设置,它是 null
,条件为假,这个 <if>
标签内的 SQL 会被完全忽略。
-
同理,passWord
和 realName
也为空,它们的条件判断也为假,对应的 SQL 也不会生成。
-
生成最终 SQL:
最终发送到数据库的 SQL 语句变成了:
DELETE FROM manage
WHERE 1=1
AND id = ?;
PreparedStatement 的参数 ?
会被设置为 5
。
-
执行删除:数据库执行这条 SQL,删除所有 id = 5
的记录。
为什么需要 WHERE 1=1
?
这是一个常见的 SQL 技巧,目的是为了避免动态拼接 SQL 时出现语法错误。
1=1
是一个永远为真的条件,它确保了 WHERE
关键字后面总是有内容,从而让后续的 AND ...
能够正确地拼接上去。
总结
所以,并不是实体类本身能删除数据,而是:
-
实体类充当了“条件容器”的角色:它的属性值决定了删除操作的条件。
-
动态 SQL (<if>
标签) 是真正的“魔法”:它根据实体对象中哪些属性有值,来动态地、有选择地生成 WHERE 子句的条件。
-
WHERE 1=1
是语法糖:它保证了动态拼接过程的灵活性,避免了语法错误。
这种设计非常灵活和强大。你可以通过设置实体对象的不同属性组合,来实现多种不同的删除条件,而无需编写多个独立的删除方法。例如:
警告:使用这种方式要非常小心,如果你传入一个全新的、所有属性都为 null
的实体对象,生成的 SQL 将是 DELETE FROM manage WHERE 1=1
,这会清空整个表!在实际项目中,通常会在业务层进行校验,防止误删。