MyBatisGenerator查询方法的使用中的Example对象
背景:
MyBatisGenerator(MBG)是MyBatis官方提供的代码生成器。它可以根据数据库的表结构自动生成POJO类、持久层接口与映射文件,极大减少了代码的编写量,提高开发效率。
上图是通过MBG生成的一些类和文件,Product类是实体类,ProductExample是执行查询语句时需要使用到的类,除了查询方法以外的方法都比较简单,不做赘述。
问题描述:
在查询时候,必须要用到ProductExample类,新建该类实例,然后通过该实例创建内部类Criteria对象,通过criteria对象向sql语句中添加条件,如下代码是模糊查询的示例,该案例查询出了name中带有“百战”并且price在0.0到20000.0之间的product
@Test
public void testFindAnd(){
//创建Example对象
ProductExample example = new ProductExample();
//创建criteria
ProductExample.Criteria criteria = example.createCriteria();
//添加模糊查询条件
criteria.andProductnameLike("%百战%");
criteria.andPriceBetween(0.0,20000.0);
//执行sql语句
List<Product> all = productMapper.selectByExample(example);
//输出结果
all.forEach(System.out::println);
}
在执行查询语句时,可以理解为一个Example对象对应一条sql语句,而每个Example对象可以创建多个Criteria对象。一般情况下,新建一个Example对象后,会通过这个对象去创建一个criteria对象(含有or的方法除外),通过这一个criteria不停的调用一系列and方法向sql语句中添加条件。让我疑惑的是,如果同一个Example对象创建了多个criteria,每个criteria控制一个条件,那么执行sql语句时,会把所有条件都加入吗?N个criteria对象,每个控制一个条件,是否等同于一个criteria对象控制N个条件?
测试过程分析:
针对上述问题进行如下测试
Product表:
1.一个criteria,添加一个条件
@Test
public void test1(){
//创建example对象
ProductExample example = new ProductExample();
//通过该example创建第一个criteria
ProductExample.Criteria criteria = example.createCriteria();
//通过criteria添加查询条件
criteria.andProductnameLike("%百战%");
//执行查询语句
List<Product> all = productMapper.selectByExample(example);
//输出
all.forEach(System.out::println);
}
2.一个criteria,添加两个条件
@Test
public void test2(){
//创建example对象
ProductExample example = new ProductExample();
//通过该example创建第一个criteria
ProductExample.Criteria criteria = example.createCriteria();
//通过criteria添加两个查询条件
criteria.andProductnameLike("%百战%");
criteria.andPriceBetween(0.0,2.0);
//查询并输出
List<Product> all = productMapper.selectByExample(example);
all.forEach(System.out::println);
}
添加了两个条件,没有符合的produt
3.一个example创建的两个criteria,各添加一个条件
@Test
public void test3(){
//创建example对象
ProductExample example = new ProductExample();
//通过该example创建第一个criteria
ProductExample.Criteria criteria = example.createCriteria();
//通过criteria添加查询条件
criteria1.andProductnameLike("%百战%");
//通过该example创建第二个criteria
ProductExample.Criteria criteria1 = example.createCriteria();
//通过criteria1添加查询条件
criteria.andPriceBetween(0.0,20000.0);
//查询并输出
List<Product> all = productMapper.selectByExample(example);
all.forEach(System.out::println);
}
结果和上面查询出来的不一样。查询出了满足第一个但不满足第二条件的数据。说明第二个条件未添加进去
交换上面两个criteria添加的条件
@Test
public void test2(){
//创建example对象
ProductExample example = new ProductExample();
//通过该example创建第一个criteria
ProductExample.Criteria criteria = example.createCriteria();
//通过criteria添加查询条件
criteria.andPriceBetween(0.0,20000.0);
//通过该example创建第二个criteria
ProductExample.Criteria criteria1 = example.createCriteria();
//通过criteria1添加查询条件
criteria1.andProductnameLike("%百战%");
//查询并输出
List<Product> all = productMapper.selectByExample(example);
all.forEach(System.out::println);
}
发现查询语句和查询出来的结果不一样。查询出了满足第一个但不满足第二个条件的数据。
得出结论:
根据这个测试结果,可以发现,N个criteria对象,每个控制一个条件,不等同于一个criteria对象控制N个条件。我目前的猜测是,当一个example创建两个criteria时,会执行带有第一个criteria添加的条件的sql语句。(仅仅是根据测试结果猜测,后续还需要看源码分析,有大佬懂的可以在评论区留言指正一下)