三、通用Mapper实现复杂查询-ExampleMapper
3.1 QBC查询
QBC既Query By Criteria,QBC查询是将查询条件通过Java对象进行模块化封装。
Criterion是一个内部类,是Criterion的复数形式,既准则标准的意思;与MBG生成的复杂查询条件的实体类CatExample中的Criterion内部类代码是一样的,也都提供了createCriteria方法,创建复合查询条件
MBG生成的封装查询条件的XXXExample VS 通用Mapper的Example类
都封装了大量的查询条件。两者使用方法的不同,MBG直接针对Entity实体类生成了XXXExample,如在生成的CatExample、TeacherExample;而通用Mapper使用条件查询时则需要在新建一个Example时传入一个要查询的实体类class
Example porscheExample = new Example(Porsche.class); 复制代码
3.1.1 使用QBC查询
使用QBC创建如下复合查询
WHERE (por_id > 1 and por_stock > 20) OR ( por_price < 1000000 and por_stock > 20) 复制代码
在PorscheService中增加getPorschesByPriceAndStock方法
List<Porsche> getPorschesByPriceAndStock(Example porscheExample); 复制代码
在PorscheServiceImpl中增加getPorschesByPriceAndStock方法的实现
@Override public List<Porsche> getPorschesByPriceAndStock(Example porscheExample) { return porscheMapper.selectByExample(porscheExample); } 复制代码
在PorscheServiceTest增加getPorscheByPriceAndStock的测试方法,查询条件的构建过程查看注释。
@Test public void getPorscheByPriceAndStock(){ Example porscheExample = new Example(Porsche.class); // WHERE (por_id > 1 and por_stock > 20) OR ( por_price < 1000000 and por_stock > 20) // 创建两个查询条件,WHERE关键字后面的两个括号分别对应两个查询条件 Example.Criteria criteria1 = porscheExample.createCriteria(); Example.Criteria criteria2 = porscheExample.createCriteria(); // 设置两个查询条件 criteria1.andGreaterThan("porId",1) .andGreaterThan("porStock",20); criteria2.andLessThan("porPrice",1000000d) .andGreaterThan("porStock",20); // 通过OR连接查询条件1--criteria1和查询条件2--criteria2 // porschExample就相当于select 字段名 from 表明 WHERE criteria 1 // 只需要调用or方法将criteria2连接上,就构成了完成的SQL语句 // select 字段名 from 表明 WHERE (criteria1) OR (criteria2) porscheExample.or(criteria2); List<Porsche> porscheList = porscheService.getPorschesByPriceAndStock(porscheExample); for (Porsche porsche : porscheList) { System.out.println("查询到的内容为:" + porsche); } } 复制代码
执行测试
3.1.2 QBC其他设置
QBC查询同时可以设置如排序、去重、设置查询的字段等,在getPorscheByPriceAndStock测试方法中增加相关代码,
porscheExample.setDistinct(true); porscheExample.orderBy("porPrice").asc().orderBy("porName").desc(); porscheExample.selectProperties("porName","porPrice"); 复制代码
再次执行测试
查看控制台删除的SQL语句,构建的复合条件在SQL执行时生效。
四、通用Mapper实现分页-RowBoundsMapper
4.1 分页相关方法
// 根据example条件和RowBounds进行分页查询 List<T> selectByExampleAndRowBounds(Object example, RowBounds rowBounds); // 根据实体属性和RowBounds进行分页查询 List<T> selectByRowBounds(T record, RowBounds rowBounds); 复制代码
4.1.1 selectByRowBounds
在PorscheService接口中增加分页查询方法getPorschesByRowBounds
List<Porsche> getPorschesByRowBounds(Porsche record, RowBounds rowBounds); 复制代码
在PorscheServiceImpl中实现分页查询方法getPorschesByRowBounds
@Override public List<Porsche> getPorschesByRowBounds(Porsche record, RowBounds rowBounds) { return porscheMapper.selectByRowBounds(record,rowBounds); } 复制代码
增加该方法的测试代码
@Test public void getPorschesByRowBounds(){ int pageNo = 2; int pageSize = 3; int index = (pageNo - 1) * pageSize; RowBounds rowBounds = new RowBounds(index, pageSize); List<Porsche> porscheList = porscheService.getPorschesByRowBounds(null, rowBounds); for (Porsche porsche : porscheList) { System.out.println("查询到的内容为:" + porsche); } } 复制代码
执行测试
根据控制台输出的SQL语句,说明通用Mapper还是查询出所有的数据,在内存中进行的分页操作,”假分页“,不推荐使用这个分页查询,推荐使用PageHelper插件实现真正的分页
4.2 @Transient
一般情况下,实体类中的属性和数据库表中的字段都是一一对应的,但是有些属性可能在数据库中没有对应的字段,这时候就需要使用@Transient注解标明这不是表中的字段。
五、通用Mapper的逆向工程
5.1 通用Mapper的逆向工程
通用Mapper的逆向工程生成的代码与原生MyBatis生成的代码稍有区别,首先都包含Entity实体类、XxxMapper接口以及XxxMapper.xml,但是通用Mapper生成的Entity实体类中会包含如@Table注解、@Column注解、@Id注解以及@GeneratedValue等注解;生成的XxxMapper接口继承Mapper<Xxx>类;生成的XxxMapper.xml中没有SQL语句,只有一个resultMap标签。
5.2 使用通用Mapper的逆向工程
新建一个项目common-mapper-mbg,该项目的用到的依赖、Spring配置及MyBatis配置与general-mapper项目用到的一致,差异在于新建的general-mapper-mbg项目中不包含Entity实体类Mapper接口以及Service类和测试类等。
在common-mapper-mbg项目的pom.xml文件中增加通用Mapper的代码生成器依赖及maven插件,通过maven插件执行代码生成器生成代码,通过用Java代码或者命令行的方式也可运行代码生成器,这里不再赘述。
<dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-generator</artifactId> <version>1.0.0</version> </dependency> 复制代码
resources目录下新增generatorConfig.xml
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <properties resource="db.properties"/> <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat"> <property name="beginningDelimiter" value="`"/> <property name="endingDelimiter" value="`"/> <!--通用Mapper的MBG插件--> <plugin type="tk.mybatis.mapper.generator.MapperPlugin"> <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/> <property name="caseSensitive" value="true"/> </plugin> <jdbcConnection driverClass="${jdbc_driver}" connectionURL="${jdbc_url}" userId="${jdbc_username}" password="${jdbc_password}"> </jdbcConnection> <javaModelGenerator targetPackage="com.citi.entity" targetProject="./src/main/java"/> <sqlMapGenerator targetPackage="mappers" targetProject="./src/main/resources"/> <javaClientGenerator targetPackage="com.citi.mapper" targetProject="./src/main/java" type="XMLMAPPER"/> <!--tableName="%"表示所有表都参与逆向工程--> <table tableName="t_teacher" domainObjectName="Teacher"> <generatedKey column="id" sqlStatement="Mysql"/> </table> </context> </generatorConfiguration> 复制代码
pom.xml中增加插件
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.7</version> <configuration> <configurationFile> ${basedir}/src/main/resources/generatorConfig.xml </configurationFile> <overwrite>true</overwrite> <verbose>true</verbose> </configuration> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>4.0.0</version> </dependency> </dependencies> </plugin> </plugins> </build> 复制代码
运行通用Mapper的MBG
代码生成器运行成功
5.3 测试通用Mapper生成的代码
新建代码生成器生成的TeacherMapper的测试类
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:application.xml") public class TeacherMapperTest { @Resource private TeacherMapper teacherMapper; @Test public void selectAll(){ List<Teacher> teachers = teacherMapper.selectAll(); for (Teacher teacher : teachers) { System.out.println("查询到的内容为:" + teacher.getTeacherName()); } } } 复制代码
执行该测试
控制台成功输出查询内容,通用Mapper的逆向工程生成的代码验证成功。