mybatis的注意事项

1,查询的时候不为空的判断,使用choose+多个when

<select id="findByCondition" resultType="com.lkb.bean.mail.CountEmailBank"
		parameterType="com.lkb.bean.mail.CountEmailBank">
		select * from t_countemailbank
		where bankname=#{bankname,jdbcType=VARCHAR}
		<choose>
			<when test="statementdate!=null">
				and statementDate = #{statementdate, jdbcType=TIMESTAMP}
			</when>
			<otherwise>
				and statementDate is null
			</otherwise>
		</choose>
		and mouldId = #{mouldid, jdbcType=INTEGER} limit 1
	</select>

2,更新时候不为空的判断用set+多个if

<update id="updateNumByCondition" parameterType="com.lkb.bean.mail.CountEmailBank">
		update t_countemailbank
		<set>
			<if test="num != null">
				num = #{num, jdbcType=INTEGER},
			</if>
			<if test="lastmodifydate != null">
				lastModifyDate = #{lastmodifydate, jdbcType=TIMESTAMP}
			</if>
		</set>
		where bankname=#{bankname, jdbcType=VARCHAR}
		<choose>
			<when test="statementdate!=null">
				and statementDate = #{statementdate, jdbcType=TIMESTAMP}
			</when>
			<otherwise>
				and statementDate is null
			</otherwise>
		</choose>
		and mouldId = #{mouldid, jdbcType=INTEGER}
	</update>

3,参数为array集合时

<select id="getStudentListByIds_foreach_array" resultMap="resultMap_studentEntity">
		select * from student s
		where s.id in
		<foreach collection="array" item="ids" open="(" separator="," close=")">
			#{ids}
		</foreach>
	</select>

4,参数为list集合时

<select id="getStudentListByIds_foreach_list" resultMap="resultMap_studentEntity">
		select * from student s
		where s.id in
		<foreach collection="list" item="idList" open="(" separator="," close=")">
			#{idList}
		</foreach>
	</select>


5,xml中某些特殊符号作为内容时需要转义

&lt; <   
&gt; >   
&amp; &   
&apos; '   
&quot; " 

在mapper文件中写sql语句时,为避免不必要的麻烦(如上述特殊符号等),建议用<![CDATA[ ]]>来标记不应有xml解析器的进行解析的文本内容,由<![CDATA[ ]]>包含的内容都会被及西区忽略,如:

<select id="getAccountsByBranch" resultType="Account" parameterType="string">  
    <![CDATA[SELECT * FROM t_acctreg_accounts where acctno < #{acctno}]]>  
</select>  

一般情况下是可以的,但是如果这样写:

<select id="getAccountErrorCount" resultType="int" parameterType="map">  
    <![CDATA[ 
    select count(*) from t_acctreg_accounterror 
    <where> 
        <if test="enddate != null and enddate != ''"> 
            createdate <= #{enddate} 
        </if> 
        <if test="acctno != null and acctno != ''"> 
            AND acctno LIKE '%'||#{acctno}||'%' 
        </if> 
    </where> 
    ]]>  
</select> 

则会报错,这是由于该sql含有动态语句,如where+if的动态语句不能放在<![CDATA[ ]]>中,否则将导致不能识别sql动态判断部分而报错,可以进行如下调整:

<select id="getAccountErrorCount" resultType="int" parameterType="map">  
    select count(*) from t_acctreg_accounterror  
    <where>  
        <if test="enddate != null and enddate != ''">  
            <![CDATA[createdate <= #{enddate}]]>  
        </if>  
        <if test="acctno != null and acctno != ''">  
            <![CDATA[AND acctno LIKE '%'||#{acctno}||'%']]>  
        </if>  
    </where>  
</select> 
在一般的传参过程中,最好给参数指定jdbcType类型!








<think>嗯,用户问的是MyBatis中updateById的使用注意事项。我需要先回忆一下MyBatis的基础知识,特别是关于更新操作的部分。首先,updateById通常不是MyBatis自带的,而是MyBatis Plus中的方法,对吧?所以可能用户混淆了MyBatisMyBatis Plus。这点需要明确说明,避免用户误解。 接下来,用户可能想知道在使用类似updateById这样的方法时需要注意什么。首先,要确保主键正确,因为根据ID更新,如果主键字段不对或者值错误,会导致更新失败或者影响错误的数据。另外,字段是否为null的问题,比如如果实体类中有null字段,是否会被更新到数据库,这取决于框架的配置,比如MyBatis Plus的全局策略或者字段注解。 然后,乐观锁的问题。如果用户的项目中使用了乐观锁,比如有@Version注解的字段,updateById会自动处理版本号,这时候需要确保实体类中的版本号是正确的,否则可能会更新失败。这一点很重要,容易被忽略。 还有SQL注入的风险,虽然MyBatis Plus生成的SQL一般参数化,但用户如果自定义了update语句,需要注意避免拼接字符串,防止注入攻击。此外,批量操作时的性能问题,频繁的单条更新会影响效率,应该考虑批量更新方法。 另外,数据库权限问题,用户是否有执行update的权限,这也是一个潜在的问题点。事务管理方面,确保在需要事务的方法上添加注解,保证数据一致性。最后,日志和错误排查,开启SQL日志可以帮助调试。 不过,用户提到的是updateById,可能需要具体到MyBatis的实现,比如自己写的update语句,这时候注意事项可能有所不同,比如动态SQL的编写,确保非空字段的判断,参数的正确传递等。但根据常见情况,用户可能指的是MyBatis Plus的updateById,所以应该以这个为前提来回答。 总结下来,注意事项大概包括:确认主键、非null字段处理、乐观锁、SQL注入、批量操作、权限、事务、日志等。需要分点说明,结构清晰,每个点详细解释原因和解决方法。同时提醒用户注意MyBatisMyBatis Plus的区别,避免混淆。可能还需要提到实体类映射是否正确,比如字段名和数据库列名是否对应,使用@TableId注解等。 最后,检查是否有遗漏点,比如触发器和数据库约束是否会影响更新结果,或者并发更新时的锁问题,但乐观锁已经覆盖了部分。还有,空值更新是否需要动态SQL,比如使用<if>标签来判断字段是否为null,避免覆盖数据库中的现有值。这点在MyBatis的XML配置中常见,需要根据业务需求决定是否更新null值。</think>以下是在MyBatis(及MyBatis Plus扩展)中使用`updateById`方法时需要注意的关键事项,按问题场景分类说明: --- ### 一、明确框架差异 1. **MyBatis原生 vs MyBatis Plus** - `updateById`是**MyBatis Plus**提供的扩展方法(需继承`BaseMapper<T>`),MyBatis原生无此方法。 - 若使用原生MyBatis,需手动编写XML映射文件或注解SQL。 --- ### 二、主键字段准确性 1. **标识主键字段** - 确保实体类主键字段用`@TableId`标注(MyBatis Plus),或XML中正确配置`<id>`。 - 错误示例:未标注主键导致更新条件错误。 ```java @TableId(value = "id", type = IdType.AUTO) // 明确主键映射 private Long id; ``` 2. **主键值有效性** - 传入实体的主键值必须非空且存在,否则可能: - 更新0条数据(无对应ID) - 因空主键抛出异常 --- ### 三、字段更新策略 1. **非空字段处理** - MyBatis Plus默认更新策略为`NOT_NULL`:**仅更新非空字段**。 - 若需强制更新字段为`null`,需: - 设置全局策略:`mybatis-plus.global-config.db-config.update-strategy=ignored` - 使用`@TableField(updateStrategy = FieldStrategy.IGNORED)`注解特定字段 2. **动态SQL控制** - 原生MyBatis中需在XML中用`<if>`手动控制更新条件: ```xml <update id="updateUser"> UPDATE user <set> <if test="name != null">name = #{name},</if> <if test="age != null">age = #{age},</if> </set> WHERE id = #{id} </update> ``` --- ### 四、并发与锁机制 1. **乐观锁配置** - 使用`@Version`注解实现乐观锁: ```java @Version private Integer version; // 更新时自动+1 ``` - 需确保数据库中存在`version`字段,更新失败会抛出`OptimisticLockException` --- ### 五、性能与批量操作 1. **避免单条循环更新** - 频繁调用`updateById`影响性能,改用`updateBatchById`批量更新(MyBatis Plus) ```java List<User> userList = ...; userService.updateBatchById(userList); // 批量执行 ``` --- ### 六、安全与事务 1. **SQL注入防范** - 避免在自定义XML中使用`${}`拼接参数,坚持用`#{}` ```xml <!-- 危险写法 --> WHERE id = ${id} <!-- 正确写法 --> WHERE id = #{id} ``` 2. **事务边界控制** - 在Service层添加`@Transactional`注解保证原子性: ```java @Transactional public void updateUser(User user) { userMapper.updateById(user); // 其他数据库操作 } ``` --- ### 七、调试与监控 1. **启用SQL日志** - 配置`application.yml`输出完整SQL: ```yaml mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` --- ### 典型错误场景 - **场景1**:实体类字段为`null`未被更新 **解决**:调整字段更新策略或检查数据赋值逻辑。 - **场景2**:更新后版本号未自增 **解决**:检查`@Version`字段是否被其他代码修改。 - **场景3**:更新影响行数为0 **解决**:检查主键值是否存在,或乐观锁版本是否匹配。 --- 通过以上要点控制,可有效规避`updateById`的常见问题,建议结合单元测试验证关键业务场景的更新逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值