作者:梁開權(quán)苫昌,叩丁狼高級(jí)講師沈自。
各位小伙伴們大家好,逍遙又跟大家見面了,在上次分享中給大家分享了如何通過注解的方式來操作MyBatis,也都僅僅局限于靜態(tài)SQL語(yǔ)句,這次給大家分享想如何通過注解的方式使用動(dòng)態(tài)SQL
準(zhǔn)備工作
事先建好表/domain/mapper/QueryObject
@Setter@Getter@ToString
public class Employee {
private Long id; //代理主鍵
private String name; //員工姓名
private String age; //員工年齡
}
public interface EmployeeMapper {
//查詢符合條件的總行數(shù)
Integer selectForCount(EmployeeQueryObject qo);
//查詢符合條件的對(duì)象
List<?> selectForList(EmployeeQueryObject qo);
}
@Setter@Getter
public class EmployeeQueryObject {
private int currentPage; //當(dāng)前頁(yè)
private int pageSize; //頁(yè)面容量
private String name; //員工姓名的模糊查詢
private Integer minAge; //員工年齡的最小值范圍查詢
private Integer maxAge; //員工年齡的最大值范圍查詢
//取值前跳過的行數(shù)
public int getStart() {
return (currentPage - 1) * pageSize;
}
}
方式1:
直接在mapper接口的方法中貼@Select注解在配置value屬性,該屬性中的SQL語(yǔ)句使用script標(biāo)簽包起來,表示里面使用了腳本語(yǔ)言
public interface EmployeeMapper {
//查詢符合條件的總行數(shù)
@Select("<script>" +
"select count(0) from employee" +
"<where>" +
"<if test='name != null'>" +
"and name like concat('%', #{name}, '%')"+
"</if>"+
"<if test='minAge != null'>" +
"and age >= #{minAge}"+
"</if>"+
"<if test='maxAge != null'>" +
"and age <= #{maxAge}"+
"</if>"+
"</where>" +
"</script>")
Integer selectForCount(EmployeeQueryObject qo);
//查詢符合條件的對(duì)象
@Select("<script>" +
"select id, name, age from employee" +
"<where>" +
"<if test='name != null'>" +
"and name like concat('%', #{name}, '%')"+
"</if>"+
"<if test='minAge != null'>" +
"and age >= #{minAge}"+
"</if>"+
"<if test='maxAge != null'>" +
"and age <= #{maxAge}"+
"</if>"+
"</where>" +
"limit #{start}, #{pageSize}" +
"</script>")
List<?> selectForList(EmployeeQueryObject qo);
}
以上代碼中存在了大量的重復(fù)代碼,比如from語(yǔ)句和where的語(yǔ)句都是一樣的,此時(shí)是這種直接注解中寫SQL的方式是不能做抽取的,怎么辦?我們可以使用另外的一種方式,把生成SQL語(yǔ)句的代碼寫在某個(gè)類的某個(gè)方法中,再告訴框架找某個(gè)類的某個(gè)方法拿到SQL語(yǔ)句即可
方式2:
自己定義一個(gè)類,在類中設(shè)計(jì)兩個(gè)方法分別用于拿到selectForCount和selectForList的SQL語(yǔ)句,在此之前先介紹MyBatis的SQL對(duì)象,該對(duì)象用于生成最終的SQL語(yǔ)句
此時(shí)我們就可以通過自己動(dòng)手創(chuàng)建SQL對(duì)象,從而拿到我們要的SQL語(yǔ)句
//員工對(duì)象的SQL提供者
public class EmployeeSQLProvider {
//拿到查詢總行數(shù)的SQL語(yǔ)句
public String getCountSql(EmployeeQueryObject qo) {
//創(chuàng)建SQL對(duì)象并設(shè)置select語(yǔ)句要查詢的列
SQL sql = new SQL().SELECT("count(0)");
addFrom(sql); //添加from語(yǔ)句
addWhere(sql, qo); //添加where語(yǔ)句
return sql.toString();
}
//拿到查詢集合對(duì)象的SQL語(yǔ)句
public String getLimitSql(EmployeeQueryObject qo) {
SQL sql = new SQL().SELECT("id, name, age");
addFrom(sql);
addWhere(sql, qo);
return sql.toString();
}
//抽取拼接的from語(yǔ)句的方法
private void addFrom(SQL sql) {
sql.FROM("employee"); //往SQL對(duì)象中添加from語(yǔ)句
}
//抽取拼接的where語(yǔ)句的方法
private void addWhere(SQL sql, EmployeeQueryObject qo) {
//往SQL對(duì)象中動(dòng)態(tài)的添加添加
if (StringUtils.hasLength(qo.getName())) {
sql.WHERE("e.name like #{name}");
}
if (qo.getMinAge() != null) {
sql.WHERE("e.age >= #{minAge}");
}
if (qo.getMaxAge() != null) {
sql.WHERE("e.age <= #{maxAge}");
}
}
}
有了上面的哪個(gè)SQL提供者,我們就可以告訴框架找EmployeeSQLProvider對(duì)象中的方法來拿到SQL語(yǔ)句,所以我們?cè)趍apper接口的方法中使用注解@SelectProvider,并且告訴該注解找EmployeeSQLProvider類中的哪個(gè)方法拿SQL語(yǔ)句即可,所以方式2就變成一下的樣子
public interface EmployeeMapper {
//type表示提供SQL的類,method表示該類中的哪個(gè)方法
@SelectProvider(type= EmployeeSQLProvider.class, method="getCountSql")
Integer selectForCount(EmployeeQueryObject qo);
@SelectProvider(type= EmployeeSQLProvider.class, method="getLimitSql")
List<?> selectForList(EmployeeQueryObject qo);
}
對(duì)比方式1大家應(yīng)該不難發(fā)現(xiàn)方式2在配置上的簡(jiǎn)潔性,把復(fù)雜的邏輯操作拿到了代碼中,同時(shí)也能抽取重復(fù)的代碼,相對(duì)來講方式2要更好些,大家學(xué)會(huì)了嗎?本期就先分享到這來,我們下期再會(huì)