ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MyBatis 的注解式开发

MyBatis 的注解式开发 MyBatis 的注解式开发是除了 XML 映射之外的另一种主流方式。它把 SQL 直接写在 Java 接口的方法上省去了 XML 文件适合简单查询和快速开发。下面我从最基础的注解开始逐步深入到复杂的映射和动态 SQL一、为什么用注解式开发维度注解式XML 式代码密度高SQL 和 Java 在同一文件低需要单独维护 XML可读性简单查询清晰复杂查询更易读动态 SQL较复杂用SelectProvider非常灵活if、where维护成本低修改接口即改 SQL中等需同时维护接口和 XML适用场景简单 CRUD、快速开发复杂联表查询、动态条件多结论没有绝对的优劣实际项目中通常是注解和 XML 混合使用简单查询用注解复杂查询用 XML。二、基础 CRUD 注解1.Select/Insert/Update/DeletepublicinterfaceUserMapper{// 查询单条Select(SELECT * FROM user WHERE id #{id})UserselectById(Longid);// 查询列表Select(SELECT * FROM user WHERE name LIKE CONCAT(%, #{name}, %))ListUserselectByName(Stringname);// 插入使用 Options 返回自增主键Insert(INSERT INTO user(name, age, email) VALUES(#{name}, #{age}, #{email}))Options(useGeneratedKeystrue,keyPropertyid)intinsert(Useruser);// 更新Update(UPDATE user SET name #{name}, age #{age} WHERE id #{id})intupdate(Useruser);// 删除Delete(DELETE FROM user WHERE id #{id})intdeleteById(Longid);}2. 返回自增主键使用Options(useGeneratedKeys true, keyProperty id)插入后 MyBatis 会自动把生成的主键设置到对象的id属性中。UserusernewUser();user.setName(张三);userMapper.insert(user);System.out.println(新插入的IDuser.getId());// 自动回填三、参数传递1. 单个参数基本类型直接用#{参数名}即可。Select(SELECT * FROM user WHERE id #{id})UserselectById(Longid);2. 多个参数——使用Param多个参数时必须用Param注解给参数起别名。Select(SELECT * FROM user WHERE name LIKE CONCAT(%, #{name}, %) AND age #{age})ListUserselectByNameAndAge(Param(name)Stringname,Param(age)Integerage);如果没有ParamMyBatis 会用arg0、arg1或者param1、param2作为参数名非常不直观。3. 传入 POJO 对象直接用#{属性名}即可MyBatis 会自动读取对象的 getter 方法。Insert(INSERT INTO user(name, age, email) VALUES(#{name}, #{age}, #{email}))intinsert(Useruser);4. 传入 MapSelect(SELECT * FROM user WHERE name #{name} AND age #{age})ListUserselectByMap(MapString,Objectparams);调用时MapString,ObjectmapnewHashMap();map.put(name,张三);map.put(age,25);userMapper.selectByMap(map);四、结果映射——Results和Result当数据库字段名和 Java 属性名不一致时需要手动映射。Select(SELECT id, user_name, user_age FROM user WHERE id #{id})Results(iduserResultMap,value{Result(columnid,propertyid),Result(columnuser_name,propertyname),Result(columnuser_age,propertyage)})UserselectById(Longid);Results的id属性可以给这个映射起一个名字在其他方法中复用。Select(SELECT id, user_name, user_age FROM user)ResultMap(userResultMap)// 复用上面的映射ListUserselectAll();五、复杂关联查询——联表映射1. 一对一关联OnepublicclassUser{privateLongid;privateStringname;privateDeptdept;// 所属部门}// 查询用户时顺便查询部门信息Select(SELECT id, name, dept_id FROM user WHERE id #{id})Results({Result(columnid,propertyid),Result(columnname,propertyname),Result(columndept_id,propertydept,oneOne(selectcom.example.mapper.DeptMapper.selectById))})UserselectUserWithDept(Longid);2. 一对多关联ManypublicclassDept{privateLongid;privateStringname;privateListUserusers;// 部门下的所有用户}Select(SELECT * FROM dept WHERE id #{id})Results({Result(columnid,propertyid),Result(columnname,propertyname),Result(columnid,propertyusers,manyMany(selectcom.example.mapper.UserMapper.selectByDeptId))})DeptselectDeptWithUsers(Longid);六、动态 SQL——SelectProvider注解方式处理动态 SQLif、where等比较麻烦需要用SelectProvider、InsertProvider等注解。publicclassUserSqlProvider{publicStringselectByCondition(MapString,Objectparams){Stringname(String)params.get(name);Integerage(Integer)params.get(age);SQLsqlnewSQL(){{SELECT(*);FROM(user);if(name!null!name.isEmpty()){WHERE(name LIKE CONCAT(%, #{name}, %));}if(age!null){WHERE(age #{age});}ORDER_BY(id DESC);}};returnsql.toString();}}// Mapper 中使用SelectProvider(typeUserSqlProvider.class,methodselectByCondition)ListUserselectByCondition(MapString,Objectparams);注意SelectProvider的method方法返回值必须是 String即 SQL 语句。七、常用注解汇总注解用途Select查询Insert插入Update更新Delete删除Options配置选项如自增主键返回Param参数命名Results/Result结果字段映射One一对一关联查询Many一对多关联查询ResultMap复用已定义的ResultsSelectProvider动态 SQL 提供者InsertProvider/UpdateProvider/DeleteProvider同上八、注解 vs XML如何选择场景推荐方式单表 CRUD注解简单联表查询2-3张表注解复杂动态 SQL多个if、foreachXML5张表以上的复杂联表XML需要复用 SQL 片段sqlXML快速原型开发注解大型项目、长期维护混合注解XML九、混合使用的配置方式如果同时使用注解和 XMLMyBatis 会优先使用 XML如果接口方法和 XML 中的 id 相同XML 会覆盖注解。更好的做法是明确区分简单查询注解写在接口方法上复杂查询XML 写在对应的 Mapper XML 文件中接口中只声明方法不加注解// 接口中不写 Select完全由 XML 接管publicinterfaceUserMapper{ListUserselectComplex(MapString,Objectparams);}!-- XML 文件中定义复杂 SQL --selectidselectComplexresultTypeUserSELECT * FROM userwhereiftestname ! nullname LIKE CONCAT(%, #{name}, %)/if!-- 更多复杂条件 --/where/select十、最佳实践建议简单 CRUD 用注解复杂查询用 XML不要把注解搞得过于复杂。Results一定要复用通过id和ResultMap避免重复定义。动态 SQL 超过 5 行时果断用 XML可读性更好。Param不要省哪怕只有一个参数也养成习惯方便后期扩展。SelectProvider适合复杂动态 SQL但 SQL 构造逻辑建议单独放在一个类里保持 Mapper 接口的干净。
返回列表