緣由
最近使用mybatis接觸到了mybatis-generator,感覺蠻好用的,但是example部分限制較大:
- 爲每一個實體類構建了一個example類,代碼量冗餘度極高
- 條件或只能構建成
(A and B) or (C and D)
的形式 - 指定查詢字段爲
setFields("id, name")
,即參數爲字符串(雖然fields是通過插件添加上去的) - 設置order by子句爲
setOrderByClause("create_time desc")
,參數依然爲字符串
我強調後兩條參數爲字符串,是因爲這種設計不太理想:
- 一旦數據庫字段變更,重新生成文件後手寫的字段名是改不過來的
- 手寫字段名稱沒有代碼提示易出現錯誤
看來generator的example是需要改進的。
方針
邊界:單表操作
example類只爲單表操作設計,複雜sql語句在mapper中編寫。若複雜的sql語句使用代碼編寫會帶來很大的複雜度,得不償失。
目的:全代碼提示
最大限度保證使用example過程中,不出現字段名稱的字符串形式,不需要修改已經編寫的代碼或有代碼提示錯誤。
期望
setDistinct
BrandQuery brandQuery = new BrandQuery();
brandQuery.setDistinct(true);
assertTrue(brandQuery.isDistinct());
其實BrandQuery
繼承了SqlExample
,建議使用SqlExample<Brand>
替換BrandQuery
。
SqlExample<Brand> example = new SqlExample<Brand>().setDistinct(true);
assertTrue(example.isDistinct());
setFields
setFields
用於設置查詢字段,每次調用會覆蓋上次的值。
SqlExample<Brand> example = new SqlExample<Brand>()
.setFields(Brand.ID, Brand.FIRST_CHAR.as("first"));
assertEquals("id, first_char as first", example.getFields());
使用addFields
用於對字段進行追加
SqlExample<Brand> example = new SqlExample<Brand>()
.setFields(Brand.ID)
.addFields(Brand.FIRST_CHAR.as("first"));
assertEquals("id, first_char as first", example.getFields());
使用FastExample
寫法
SqlExample<Brand> example =
FastExample.fields(Brand.ID).addFields(Brand.FIRST_CHAR.as("first"));
assertEquals("id, first_char as first", example.getFields());
orderBy
orderBy
用於設置order by子句,每次調用會覆蓋上次的值。
SqlExample<Brand> example = new SqlExample<Brand>()
.orderBy(Brand.FIRST_CHAR.desc(), Brand.NAME.asc());
assertEquals("first_char desc, name asc", example.getOrderByClause());
使用andOrderBy
用於對排序字段進行追加
SqlExample<Brand> example = new SqlExample<Brand>()
.orderBy(Brand.FIRST_CHAR.desc())
.andOrderBy(Brand.NAME.asc());
assertEquals("first_char desc, name asc", example.getOrderByClause());
使用FastExample
寫法
SqlExample<Brand> example =
FastExample.orderBy(Brand.FIRST_CHAR.desc()).andOrderBy(Brand.NAME.asc());
assertEquals("first_char desc, name asc", example.getOrderByClause());
where
where
用於設置條件查詢,每次調用會覆蓋上次的值。
簡單查詢
SqlExample<Brand> example = new SqlExample<Brand>().where(Brand.ID.equal(1L));
List<Criterion<Brand>> criterionList = example.getCriterionList();
assertEquals("id = ", criterionList.get(0).getPrefix());
assertEquals(1L, criterionList.get(0).getValue());
使用FastExample
寫法
SqlExample<Brand> example = FastExample.where(Brand.ID.equal(1L));
List<Criterion<Brand>> criterionList = example.getCriterionList();
assertEquals("id = ", criterionList.get(0).getPrefix());
assertEquals(1L, criterionList.get(0).getValue());
字段與字段間的條件
SqlExample<Brand> example = new SqlExample<Brand>();
example.where(Brand.NAME.equal(Brand.FIRST_CHAR));
List<Criterion<Brand>> criterionList = example.getCriterionList();
assertEquals("name = first_char", criterionList.get(0).getPrefix());
使用表達式進行多條件查詢
SqlExample<Brand> example = new SqlExample<Brand>().where(c -> c
.and(Brand.NAME.like("%abc%"))
.and(Brand.FIRST_CHAR.like("%A%")));
List<Criterion<Brand>> criterionList = example.getCriterionList();
assertEquals("(", criterionList.get(0).getPrefix());
assertEquals("name like ", criterionList.get(1).getPrefix());
assertEquals("%abc%", criterionList.get(1).getValue());
assertEquals(" and ", criterionList.get(2).getPrefix());
assertEquals("first_char like ", criterionList.get(3).getPrefix());
assertEquals("%A%", criterionList.get(3).getValue());
assertEquals(")", criterionList.get(4).getPrefix());
爲了避免無嵌套的多條件查詢也會被括號包裹,使用andWhere
和orWhere
來追加條件
SqlExample<Brand> example = new SqlExample<Brand>()
.andWhere(Brand.NAME.like("%abc%"))
.orWhere(Brand.FIRST_CHAR.like("%A%"));
List<Criterion<Brand>> criterionList = example.getCriterionList();
assertEquals("name like ", criterionList.get(0).getPrefix());
assertEquals("%abc%", criterionList.get(0).getValue());
assertEquals(" or ", criterionList.get(1).getPrefix());
assertEquals("first_char like ", criterionList.get(2).getPrefix());
assertEquals("%A%", criterionList.get(2).getValue());
使用表達式進行嵌套條件查詢
SqlExample<Person> example = new SqlExample<Person>().where(c -> c
.and(c -> c
.and(Person.AGE.equal(13))
.or(Person.NAME.like("%abc%")))
.or(c -> c
.and(Person.AGE.equal(13))
.or(Person.NAME.like("%abc%")));
List<Criterion<Person>> criterionList = example.getCriterionList();
assertEquals("(", criterionList.get(0).getPrefix());
assertEquals("age = ", criterionList.get(1).getPrefix());
assertEquals(13, criterionList.get(1).getValue());
assertEquals(" or ", criterionList.get(2).getPrefix());
assertEquals("name like ", criterionList.get(3).getPrefix());
assertEquals("%abc%", criterionList.get(3).getValue());
assertEquals(")", criterionList.get(4).getPrefix());
assertEquals(" or ", criterionList.get(5).getPrefix());
assertEquals("(", criterionList.get(6).getPrefix());
assertEquals("age = ", criterionList.get(7).getPrefix());
assertEquals(13, criterionList.get(7).getValue());
assertEquals(" or ", criterionList.get(8).getPrefix());
assertEquals("name like ", criterionList.get(9).getPrefix());
assertEquals("%abc%", criterionList.get(9).getValue());
assertEquals(")", criterionList.get(10).getPrefix());
真實案例中if
判斷進行條件添加
Criteria<Brand> criteria = new Criteria<>();
if(!StringUtils.isNullOrEmpty(searchInput.getName())) {
criteria.and(Brand.NAME.like("%"+searchInput.getName()+"%"));
}
if(!StringUtils.isNullOrEmpty(searchInput.getFirstChar())) {
criteria.and(Brand.FIRST_CHAR.like("%"+searchInput.getFirstChar()+"%"));
}
SqlExample<Brand> example = new SqlExample<Brand>().where(criteria);
return brandDao.selectByExample(example);
使用andWhere
可以不創建Criteria
實例
SqlExample<Brand> example = new SqlExample<Brand>();
if(!StringUtils.isNullOrEmpty(searchInput.getName())) {
example.andWhere(Brand.NAME.like("%"+searchInput.getName()+"%"));
}
if(!StringUtils.isNullOrEmpty(searchInput.getFirstChar())) {
example.andWhere(Brand.FIRST_CHAR.like("%"+searchInput.getFirstChar()+"%"));
}
return brandDao.selectByExample(example);
SqlExample支持所有原查詢操作,如下
equal(value)
notEqual(value)
greaterThan(value)
greaterAndEqualThan(value)
lessThan(value)
lessAndEqualThan(value)
isNull()
isNotNull()
in(list)
notIn(list)
between(value1, value2)
notBetween(value1, value2)
like(string)
notLike(string)
引入
文件生成
- 打開generator_for_sqlexample工程
- 在工程中打開generatorConfig.xml文件修改配置信息
- 執行src中的GeneratorSqlmap類入口函數即可生成文件
安裝jar包到本地maven
generator_for_sqlexample工程lib中的mybatis-generator-sqlexample-1.1.jar包需要引入到項目中。
打開命令行工具鍵入並運行下面的命令,將mybatis-generator-sqlexample-1.1.jar包所在位置換成自己包所在的位置。
mvn install:install-file -Dfile=包所在位置\mybatis-generator-sqlexample-1.1.jar -DgroupId=org.mybatis.generator -DartifactId=mybatis-generator-sqlexample -Dversion=1.1 -Dpackaging=jar
顯示BUILD SUCCESS
後,就可在自己的maven工程中添加依賴了
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-sqlexample</artifactId>
<version>1.1</version>
</dependency>
需要注意的是,要使用mybatis-generator-sqlexample需要將Java語言級別設爲8。