mybatis中关于example类

这几天刚接触example,很多内容都是破碎的,写一篇文章加深理解。

一、什么是example类

mybatis-generator会为每个字段产生Criterion,为底层的mapper.xml创建动态sql。如果表的字段比较多,产生的example类会十分庞大。理论上通过example类可以构造你想到的任何筛选条件。在mybatis-generator中加以配置,配置数据表的生成操作就可以自动生成example了。具体配置可以参考 Mybatis-Generator的具体使用方法 - zorro的菜鸟笔记 - 博客园。

参考资料:http://www.mybatis.org/mybatis-dynamic-sql/docs/introduction.html

下面是mybatis自动生成example的使用。

二、了解example成员变量

 //作用:升序还是降序
 //参数格式:字段+空格+asc(desc)
 protected String orderByClause;  
 //作用:去除重复
 //true是选择不重复记录,false,反之
 protected boolean distinct;
 //自定义查询条件
 //Criteria的集合,集合中对象是由or连接
 protected List<Criteria> oredCriteria;
 //内部类Criteria包含一个Cretiron的集合,
 //每一个Criteria对象内包含的Cretiron之间是由  AND连接的
 public static class Criteria extends GeneratedCriteria {
  protected Criteria() {super();}
 }
 //是mybatis中逆向工程中的代码模型
 protected abstract static class GeneratedCriteria {......}
 //是最基本,最底层的Where条件,用于字段级的筛选
 public static class Criterion {......}

三、example使用前的准备

比如我的example是根据user表生成的,UserMapper属于dao层,UserMapper.xml是对应的映射文件。

UserMapper接口
long countByExample(CompetingStoreExample example);
List<CompetingStore> selectByExample(CompetingStoreExample example);

在我们的测试类里
UserExample example = new UserExample();
UserExample.Criteria criteria = example.createCriteria();

四、查询用户数量

 long count = UserMapper.countByExample(example);

类似于:select count(*) from user

五、where条件查询或多条件查询

 example.setOrderByClause(age asc"); //升序
 example.setDistinct(false); //不去重
 if(!StringUtils.isNotBlank(user.getName())){
 Criteria.andNameEqualTo(user.getName());
 }
 if(!StringUtils.isNotBlank(user.getSex())){
 Criteria.andSexEqualTo(user.getSex());
 }
 List<User> userList=userMapper.selectByExample(example);

类似于:select * from user where name={#user.name} and sex={#user.sex} order by age asc;

 UserExample.Criteria criteria1 = example.createCriteria();
 UserExample.Criteria criteria2 = example.createCriteria();
 if(!StringUtils.isNotBlank(user.getName())){
 Criteria1.andNameEqualTo(user.getName());
 }
 if(!StringUtils.isNotBlank(user.getSex())){
 Criteria2.andSexEqualTo(user.getSex());
 }
 Example.or(criteria2);
 List<User> userList=userMapper.selectByExample(example);

类似于:select * from user where name={#user.name} or sex={#user.sex} ;

六、模糊查询

 if(!StringUtils.isNotBlank(user.getName())){
 criteria.andNameLIke(%+name+%);
 }
 List<User> userList=userMapper.selectByExample(example);

类似于:select * from user where name like %{#user.name}%

七、分页查询

 int start = (currentPage - 1) * rows;
 //分页查询中的一页数量
 example.setPageSize(rows); 
 //开始查询的位置
 example.setStartRow(start);  
 List<User> userList=userMapper.selectByExample(example);

类似于:select * from user limit start to rows

如果喜欢我的文章欢迎关注我的专栏~

-----------

要使用example类,先要在项目中导入mybatis.mapper的jar包。

Mapper接口中包含了单表的增删改查以及分页功能。

给出实例:

CountryMappermapper = sqlSession.getMapper(Country.class);

//Country.class是实体类

//查询操作

List<Country>cList = mapper.select(new Country());

现在使用Example查询

Example example =new Example(Country.class);

example.createCriteria().andEqualTo(“id”,100);

//这里给出查询为id=100

cList = mapper.selectByExample(example);

 

example.setOrderByClause(“字段名ASC”); 以某字段升序排序

example.setDistinct(false)//去除重复,boolean型,true为选择不重复的记录

selectByExample()返回的是一个集合

mybatis中mapper的实例函数:
int countByExample(UserExample example) thorws SQLException:按条件计数。
int deleteByPrimaryKey(Integer id) thorws SQLException:按主键删除。
int deleteByExample(UserExample example) thorws SQLException:按条件删除。
String/Integer insert(User record) thorws SQLException:插入(返回值为id值)
User selectByPrimaryKey(Integer id) thorws SQLException:按主键查询。
List<?>selectByExample(UserExample example) thorws SQLException:按条件查询
List<?>selectByExampleWithBLOGs(UserExample example) thorws SQLException:按

条件查询(包括BLOB字段)。只有当数据表中的字段类型有为二进制的才会产生。
int updateByPrimaryKey(User record) thorws SQLException:按主键更新
int updateByPrimaryKeySelective(User record) thorws SQLException:按主键更新值不为null的字段

int updateByExample(User record, UserExample example) thorws SQLException: 按条件更新

int updateByExampleSelective(User record, UserExample example)thorws

SQLException:按条件更新值不为null的字段

mybatis中mapper的实例函数详解:
selectByPrimaryKey()

Country country = ##Mapper.selectByPrimaryKey(100);

相当于select * from user where id = 100

还有一些方法不在这里赘述,可以参考mybatis中的example

Example类是什么?

Example类指定如何构建一个动态的where子句. 表中的每个non-BLOB列可以被包括在where子句中. 例子是展示此类用法的最好方式.

Example类可以用来生成一个几乎无限的where子句.

Example类包含一个内部静态类 Criteria 包含一个用 anded 组合在where子句中的条件列表. Example类包含一个 List 属性,所有内部类Criteria中的子句会用 ored组合在一起. 使用不同属性的 Criteria 类允许您生成无限类型的where子句.

创建 Criteria 对象 可以使用Example类中的 createCriteria() 或者 or() . 如果 Criteria 对象是用 createCriteria() 创建的,它会自动为 List 属性添加一个 Criteria 对象 - 这使得它更容易写一个简单的where子句, 如果您不需要 or 或者其他几个子句组合的话. 用 or(Criteria criteria) 方法创建 Criteria 对象, 方法里的 criteria 对象会被添加进 Criteria 对象的列表中.

重要 我们推荐您只使用 or() 方法创建 Criteria 对象. 我们相信这种方法使代码更有可读性.

如何生成Example类?

mybatis的的配置文件可以使用mybatis-generator工具生成,它就可以帮我们生成example类。
根据 Mybatis 代码生成工具文档,需要一个配置文件,这里命名为:mbgConfiguration.xml放在 src 目录下. 配置文件内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
      PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
      "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

    <generatorConfiguration>

      <!-- 配置mysql 驱动jar包路径.用了绝对路径 -->
      <classPathEntry location="D:\Work\Java\eclipse\workspace\myBatisGenerator\WebContent\WEB-INF\lib\mysql-connector-java-5.1.22-bin.jar" />

      <context id="yihaomen_mysql_tables" targetRuntime="MyBatis3">

        <!-- 为了防止生成的代码中有很多注释,比较难看,加入下面的配置控制 -->
        <commentGenerator>
          <property name="suppressAllComments" value="true" />
          <property name="suppressDate" value="true" />
        </commentGenerator>
        <!-- 注释控制完毕 -->

        <!-- 数据库连接 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
            connectionURL="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8"
            userId="root"
            password="password">
        </jdbcConnection>

        <javaTypeResolver >
          <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- 数据表对应的model 层  -->
        <javaModelGenerator targetPackage="com.yihaomen.model" targetProject="src">
          <property name="enableSubPackages" value="true" />
          <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!-- sql mapper 隐射配置文件 -->
        <sqlMapGenerator targetPackage="com.yihaomen.mapper"  targetProject="src">
          <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <!-- 在ibatis2 中是dao层,但在mybatis3中,其实就是mapper接口 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.yihaomen.inter"  targetProject="src">
          <property name="enableSubPackages" value="true" />
        </javaClientGenerator>

        <!-- 要对那些数据表进行生成操作,必须要有一个. -->
        <table schema="mybatis" tableName="category" domainObjectName="Category" 
            enableCountByExample="false" enableUpdateByExample="false"
            enableDeleteByExample="false" enableSelectByExample="false"
            selectByExampleQueryId="false">     
        </table>

      </context>
    </generatorConfiguration>

 

当我们需要生成example类的时候,需要table里面去掉

enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false"

 

 

example如何使用?

简单查询

这个例子展示了如何用生成后的Example类去生成一个简单的where子句:

TestTableExample example = new TestTableExample();

example.createCriteria().andField1EqualTo(5);
作为另一种选择, 下面的方式也是可以的:

TestTableExample example = new TestTableExample();

example.or().andField1EqualTo(5);
在上面的例子中, 动态生成的where子句是:

where field1 = 5

下面的例子展示了如何用生成后的Example类去生成一个复杂的where子句 (用到了 JSE 5.0 的泛型):

TestTableExample example = new TestTableExample();

example.or()
.andField1EqualTo(5)
.andField2IsNull();

example.or()
.andField3NotEqualTo(9)
.andField4IsNotNull();

List field5Values = new ArrayList();
field5Values.add(8);
field5Values.add(11);
field5Values.add(14);
field5Values.add(22);

example.or()
.andField5In(field5Values);

example.or()
.andField6Between(3, 7);

在上面的例子中, 动态生成的where子句是:

where (field1 = 5 and field2 is null)
or (field3 <> 9 and field4 is not null)
or (field5 in (8, 11, 14, 22))
or (field6 between 3 and 7)
将会返回满足这些条件的记录结果.

去重复查询
您可以在所有的Example类中调用 setDistinct(true) 方法进行强制去重复查询.

Criteria类
Criteria 内部类的每个属性都包含 andXXX 方法,以及如下的标准的SQL查询方法:

IS NULL - 指相关的列必须为NULL
IS NOT NULL - 指相关的列必须不为NULL
= (equal) - 指相关的列必须等于方法参数中的值
<> (not equal) - 指相关的列必须不等于方法参数中的值

(greater than) - 指相关的列必须大于方法参数中的值
= (greater than or equal) - 指相关的列必须大于等于方法参数中的值
< (less than) - 指相关的列必须小于于方法参数中的值
<= (less than or equal) - 指相关的列必须小于等于方法参数中的值
LIKE - 指相关的列必须 “like” 方法参数中的值. 这个方法不用必须加入 ‘%’, 您必须设置方法参数中的值.
NOT LIKE - 指相关的列必须 “not like” 方法参数中的值. 这个方法不用必须加入 ‘%’, 您必须设置方法参数中的值.
BETWEEN - 指相关的列必须在 “between” 方法参数中的两个值之间.
NOT BETWEEN - 指相关的列必须不在 “not between” 方法参数中的两个值之间.
IN - 指相关的列必须在传入的方法参数的list中.
NOT IN - 指相关的列必须不在传入的方法参数的list中.

        之前用Mybatis框架反向的实体,还有实体里面的Example,之前只是知道Example里面放的是条件查询的方法,可以一直不知道怎么用,到今天才开始知道怎么简单的用。

在我们前台查询的时候会有许多的条件传过来:先看个例子:

  1. public List<Contact> searchByExample(Contact contact) {
  2. System.out.println("searchByExampleContact");
  3. ContactExample example = new ContactExample();
  4. ContactExample.Criteria cri = example.createCriteria();
  5. // //////////////////////////////////////////////////////////
  6. if (this.objectAttrNullCheck(contact, "username"))
  7. cri.andUsernameEqualTo(contact.getUsername());
  8. if (this.objectAttrNullCheck(contact, "password"))
  9. cri.andPasswordEqualTo(contact.getPassword());
  10. ContactMapper vcontactMapper = sqlSession
  11. .getMapper(ContactMapper.class);
  12. List<Contact> returnList = vcontactMapper.selectByExample(example);
  13. return returnList;
  14. }

这是简单的用户登录的后台代码,example中有一个Criterria的方法,里面

andUsernameEqualTo  
andPasswordEqualTo

都是在生成example的时候生成的。这两个方法是判断单值的。简单介绍下,都是百度的:

  • Criteria

Criteria包含一个Cretiron的集合,每一个Criteria对象内包含的Cretiron之间是由AND连接的,是逻辑与的关系。

oredCriteria

Example内有一个成员叫oredCriteria,是Criteria的集合,就想其名字所预示的一样,这个集合中的Criteria是由OR连接的,是逻辑或关系。oredCriteria就是ORed Criteria。

其他

Example类的distinct字段用于指定DISTINCT查询。

orderByClause字段用于指定ORDER BY条件,这个条件没有构造方法,直接通过传递字符串值指定。

  1. import java.io.IOException;
  2. import java.io.Reader;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import org.apache.ibatis.io.Resources;
  6. import org.apache.ibatis.session.SqlSession;
  7. import org.apache.ibatis.session.SqlSessionFactory;
  8. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  9. import org.apache.log4j.pattern.ClassNamePatternConverter;
  10. import org.springframework.context.ApplicationContext;
  11. import org.springframework.context.support.ClassPathXmlApplicationContext;
  12. import cn.itcast.ssm.mapper.ItemsMapper;
  13. import cn.itcast.ssm.po.ItemsExample;
  14. public class Student {
  15. public static void main(String[] args) throws IOException {
  16. /*方式一 */
  17. ItemsExample itemsExample1 = new ItemsExample();
  18. itemsExample1.or().andIdEqualTo(5).andNameIsNotNull();
  19. itemsExample1.or().andPicEqualTo("xxx").andPicIsNull();
  20. List<Integer> fieldValues = new ArrayList<Integer>();
  21. fieldValues.add(8);
  22. fieldValues.add(11);
  23. fieldValues.add(14);
  24. fieldValues.add(22);
  25. itemsExample1.or().andIdIn(fieldValues);
  26. itemsExample1.or().andIdBetween(5, 9);
  27. /* 方式二 criteria1与criteria2是or的关系 */
  28. ItemsExample itemsExample2 = new ItemsExample();
  29. ItemsExample.Criteria criteria1 = itemsExample2.createCriteria();
  30. criteria1.andIdIsNull();
  31. criteria1.andPriceEqualTo((float) 3);
  32. ItemsExample.Criteria criteria2 = itemsExample2.createCriteria();
  33. criteria2.andNameIsNull();
  34. criteria2.andIdGreaterThanOrEqualTo(5);
  35. itemsExample2.or(criteria2);
  36. //方式一和方式二是等价的
  37. // spring获取mapper代理对象
  38. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
  39. ItemsMapper itemsMapper = (ItemsMapper) applicationContext.getBean("itemsMapper");
  40. itemsMapper.countByExample(itemsExample2);
  41. // 获取SqlSessionFactory
  42. String resource = "SqlMapConfig.xml";
  43. Reader reader = Resources.getResourceAsReader(resource);
  44. SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
  45. // 获取SqlSession
  46. SqlSession sqlSession = sqlMapper.openSession();
  47. }
  48. }

avaBeans类的成员变量一般称为属性(property)。对每个属性访问权限一般定义为private或protected,而不是定义为public的。注意:属性名必须以小写字母开头。对每个属性,一般定义两个public方法,它们分别称为访问方法(getter)和修改方法(setter),允许容器访问和修改bean的属性。

public String getColor();

public void setColor(String);

一个例外是当属性是boolean类型时,访问器方法应该定义为isXxx()形式。

对象类型

虽然可以明确的引用对象的属性名了,但如果要在if元素中测试传入的user参数,仍然要使用_parameter来引用传递进来的实际参数,因为传递进来的User对象的名字是不可考的。如果测试对象的属性,则直接引用属性名字就可以了。

测试user对象:

<if test="_parameter != null">

传入对象属性

<if test="name != null">

 

map类型

传入map类型,直接通过#{keyname}就可以引用到键对应的值。使用@param注释的多个参数值也会组装成一个map数据结构,和直接传递map进来没有区别。

mapper接口:

int updateByExample(@Param("user") User user, @Param("example") UserExample example);

sql映射:

  1. <update id="updateByExample" parameterType="map" >
  2. update tb_user
  3. set id = #{user.id,jdbcType=INTEGER},
  4. ...
  5. <if test="_parameter != null" >
  6. <include refid="Update_By_Example_Where_Clause" />
  7. </if>

注意这里测试传递进来的map是否为空,仍然使用_parameter以上参考:http://blog.51cto.com/tianxingzhe/1741268

再来看看我的项目中的,我写的是项目的接口开发,前端要穿写条件进来查询,前端的传参格式:

  1. 传参格式:
  2. * {
  3. "currPage": 0,
  4. "startRow": 0,
  5. "pageSize": 20,
  6. "map":{
  7. "andStealtollTypeEqualTo":1
  8. }
  9. }

注意map里面的传的参数格式:全部是example里面的参数格式,如果还要传入什么参数直接在里面加(相当于前端传过来的条件),这些条件全部放进map里面,

  1. HisVehReviewHandleExample example = new HisVehReviewHandleExample();
  2. example.setPage(page);//将前面传过来的page数据放进example中
  3. popQeuryExample(example.getPage().getMap(), example.createCriteria());
  4. vehReviewService.queryPage(example);
  5. Map<String, Object> map = new HashMap<String, Object>();
  6. map.put("page", page);
  7. //map.put("typeCount", value);
  8. result.setData(map);
  9. writeJson(response, JSON.toJSON(result));

service层:

  1. public Page<HisVehReviewHandle> queryPage(HisVehReviewHandleExample example) {
  2. Page<HisVehReviewHandle> page = example.getPage();
  3. List<HisVehReviewHandle> list = HisVehReviewHandleMapper.selectByExample(example);
  4. System.out.println("查询list成功"+list.get(0).getStealtollType()+" "+list.get(0).getStealtollTypeName());
  5. int count = HisVehReviewHandleMapper.countByExample(example);
  6. page.setRows(list);
  7. page.setTotalCount(count);
  8. return page;
  9. }

sql语句查询exaple的:

  1. <select id="selectByExample" parameterType="com.vrview.ssm.model.example.HisVehReviewHandleExample" resultMap="BaseResultMap">
  2. <!--
  3. WARNING - @mbggenerated
  4. This element is automatically generated by MyBatis Generator, do not modify.
  5. This element was generated on Wed Jan 17 10:03:58 CST 2018.
  6. -->
  7. <include refid="OracleDialectPrefix" />
  8. select
  9. <if test="distinct">
  10. distinct
  11. </if>
  12. <include refid="Base_Column_List" />
  13. from HIS_VEH_REVIEW_HANDLE
  14. <if test="_parameter != null">
  15. <include refid="Example_Where_Clause" />
  16. </if>
  17. <if test="orderByClause != null">
  18. order by ${orderByClause}
  19. </if>
  20. <include refid="OracleDialectSuffix" />
  21. </select>

sql语句,用来查询数量的:

  1. <select id="countByExample" parameterType="com.vrview.ssm.model.example.HisVehReviewHandleExample" resultType="java.lang.Integer">
  2. <!--
  3. WARNING - @mbggenerated
  4. This element is automatically generated by MyBatis Generator, do not modify.
  5. This element was generated on Wed Jan 17 10:03:58 CST 2018.
  6. -->
  7. select count(*) from HIS_VEH_REVIEW_HANDLE
  8. <if test="_parameter != null">
  9. <include refid="Example_Where_Clause" />
  10. </if>
  11. </select>

关于参数_paramerter:参考:http://blog.csdn.net/u014476019/article/details/45878771
这部分就是对criteria里面的参数进行判断,进而根据条件查询。

  1. <sql id="Example_Where_Clause">
  2. <where>
  3. <foreach collection="oredCriteria" item="criteria" separator="or">
  4. <if test="criteria.valid">
  5. <trim prefix="(" prefixOverrides="and" suffix=")">
  6. <foreach collection="criteria.criteria" item="criterion">
  7. <choose>
  8. <when test="criterion.noValue">//没有值
  9. and ${criterion.condition}
  10. </when>
  11. <when test="criterion.singleValue">//单个值
  12. and ${criterion.condition} #{criterion.value}
  13. </when>
  14. <when test="criterion.betweenValue">//区间值,范围查询
  15. and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
  16. </when>
  17. <when test="criterion.listValue">//一组值
  18. and ${criterion.condition}
  19. <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
  20. #{listItem}
  21. </foreach>
  22. </when>
  23. </choose>
  24. </foreach>
  25. </trim>
  26. </if>
  27. </foreach>
  28. </where>
  29. </sql>