今天一个道友问我,知道如何利用XML的方式来构建动态SQL,MyBatis是否能够利用注解完成动态SQL的构建呢?!!答案是肯定的,MyBatis 提供了注解,@InsertProvider,@UpdateProvider,@DeleteProvider 和@SelectProvider,来帮助构建动态 SQL 语句,然后让MyBatis 执行这些 SQL 语句。
简单示例:创建一个 TutorDynaSqlProvider.JAVA 类,以及 findTutorByIdSql()方法
package com.test.myBatisTest;import org.Apache.ibatis.jdbc.SQL;public class TutorDynaSqlProvider { public String findTutorByIdSql(int tutorId) { return "SELECT TUTOR_ID AS tutorId, NAME, EMAIL FROM TUTORS WHERE TUTOR_ID=" + tutorId; }}
在 TutorMApper.java 接口中创建一个映射语句
@SelectProvider(type=TutorDynaSqlProvider.class, method="findTutorByIdSql")Tutor findTutorById(int tutorId);
动态构建SQL:使用SQL类来构建动态SQL如下所示
import org.apache.ibatis.jdbc.SQL; public class TutorDynaSqlProvider { public String findTutorByIdSql(final int tutorId) { return new SQL() { { SELECT("tutor_id as tutorId, name, email"); FROM("tutors"); WHERE("tutor_id=" + tutorId); } }.toString(); }}
SQL 工具类会处理以合适的空格前缀和后缀来构造 SQL 语句。可以接受的参数类型:无参数和映射器 Mapper 接口的方法以及同类型的参数 java.util.Map。 如果映射器 Mapper 接口有多个输入参数,我们可以使用参数类型为 java.util.Map 的方法作为 SQL provider 方法。然后映射器 Mapper 接口方法所有的输入参数将会被放到 map 中,以 param1,param2 等等作为 key,将输入参数按序作为 value。 你也可以使用 0,1,2 等作为 key 值来取得输入参数。如下所示
@SelectProvider(type = TutorDynaSqlProvider.class, method = "findTutorByNameAndEmailSql")Tutor findTutorByNameAndEmail(String name, String email);public String findTutorByNameAndEmailSql(Map<String, Object> map) { String name = (String) map.get("param1"); String email = (String) map.get("param2"); // you can also get those values using 0,1 keys // String name = (String) map.get("0"); // String email = (String) map.get("1"); return new SQL() { { SELECT("tutor_id as tutorId, name, email"); FROM("tutors"); WHERE("name=#{name} AND email=#{email}"); } }.toString();}
SQL 工具类也提供了其他的方法来表示 JOINS,ORDER_BY,GROUP_BY 等等
package com.test.myBatisTest; import org.apache.ibatis.jdbc.SQL; public class TutorDynaSqlProvider { public String selectTutorById() { return new SQL() { { SELECT("t.tutor_id, t.name as tutor_name, email"); SELECT("a.addr_id, street, city, state, zip, country"); SELECT("course_id, c.name as course_name, description,start_date, end_date"); FROM("TUTORS t"); LEFT_OUTER_JOIN("addresses a on t.addr_id=a.addr_id"); LEFT_OUTER_JOIN("courses c on t.tutor_id=c.tutor_id"); WHERE("t.TUTOR_ID = #{id}"); } }.toString(); }}
package com.test.myBatisTest; import org.apache.ibatis.jdbc.SQL; public class TutorDynaSqlProvider { public String insertTutor(final Tutor tutor) { return new SQL() { { INSERT_INTO("TUTORS"); if (tutor.getName() != null) { VALUES("NAME", "#{name}"); } if (tutor.getEmail() != null) { VALUES("EMAIL", "#{email}"); } } }.toString(); }} public interface TutorMapper { @InsertProvider(type = TutorDynaSqlProvider.class, method = "insertTutor") @Options(useGeneratedKeys = true, keyProperty = "tutorId") int insertTutor(Tutor tutor);}
package com.test.myBatisTest; import org.apache.ibatis.jdbc.SQL; public class TutorDynaSqlProvider { public String updateTutor(final Tutor tutor) { return new SQL() { { UPDATE("TUTORS"); if (tutor.getName() != null) { SET("NAME = #{name}"); } if (tutor.getEmail() != null) { SET("EMAIL = #{email}"); } WHERE("TUTOR_ID = #{tutorId}"); } }.toString(); }} public interface TutorMapper { @UpdateProvider(type = TutorDynaSqlProvider.class, method = "updateTutor") int updateTutor(Tutor tutor);}
package com.test.myBatisTest; import org.apache.ibatis.annotations.DeleteProvider;import org.apache.ibatis.jdbc.SQL; public class TutorDynaSqlProvider { public String deleteTutor(int tutorId) { return new SQL() { { DELETE_FROM("TUTORS"); WHERE("TUTOR_ID = #{tutorId}"); } }.toString(); }} public interface TutorMapper { @DeleteProvider(type = TutorDynaSqlProvider.class, method = "deleteTutor") int deleteTutor(int tutorId);}
以上就是使用注解的方式来动态的构建SQL,可以说和XML方式有很大的不同,但是功能上面似乎没有XML方式的强大,我个人更喜欢使用XML的方式来构建,同时对参数进行各种操作。