mybatis-dynamic-query 3.0 update

Project location: the mybatis-Dynamic-Query

Foreword

2.0 tk.mapper complete integration, why mybatis-dynamic-query select tk.mapper integrated , and then further to 3.0 query optimization, of course, there may contrast mybatis-plus, I think everyone will be able to choose their contrasting right.

update content

  1. Add DynamicQueryBuilder step of generating DynamicQuery statement
  2. Optimization DynamicQuery add, remove, filter and sort

DynamicQueryBuilder introduced

The introduction of 3.0, is designed to allow everyone to write queries when really like to write sql (sql query strict compliance with the order), and finally by the build method to build a DynamicQuery, based on experience DynamicQueryBuilder for the case of filter conditions known.

public List<ProductsDO> getProductListByBuilder() {
  // select product_name, list_price, category
  // where (list_price > 1 and list_price < 10) and description is not null or id = 1
  // order by id desc, list_price asc
  DynamicQuery<ProductsDO> query = DynamicQueryBuilder.create(ProductsDO.class)
     .select(ProductsDO::getProductName, ProductsDO::getListPrice, ProductsDO::getCategory)
     .where(ProductsDO::getListPrice, greaterThan(BigDecimal.ONE),
                and(ProductsDO::getListPrice, lessThan(BigDecimal.TEN)))
     .and(ProductsDO::getDescription, notEqual(null))
     .or(ProductsDO::getId, isEqual(1))
     .orderBy(ProductsDO::getId, desc())
     .thenBy(ProductsDO::getListPrice, asc())
     .build();
  return productMapper.selectByDynamicQuery(query);
}

DynamicQuery screening sorting optimization

Many DynamicQuery method name was changed, and DynamicQueryBuilder remained the same, so that everyone in the more convenient to use, from the following examples we can see sorting or screening may be added at any location and determines if statement and binding

@Test
public void testGetProductListByQuery() {
    BigDecimal startPrice = BigDecimal.valueOf(1.1);
    BigDecimal endPrice = BigDecimal.valueOf(10.1);
    DynamicQuery<ProductsDO> query = DynamicQuery.createQuery(ProductsDO.class)
            .select(ProductsDO::getProductName, ProductsDO::getListPrice, ProductsDO::getCategory);
    // 根据参数添加筛选条件,这里就是我们看看开始价,结束价有没有,如果有才会放到一个组里面,
    if (Objects.nonNull(startPrice) || Objects.nonNull(endPrice)) {
        FilterGroupDescriptor<ProductsDO> priceFilterGroup = new FilterGroupDescriptor<>();
        if (Objects.nonNull(startPrice)) {
            priceFilterGroup.and(ProductsDO::getListPrice, greaterThan(startPrice));
        }
        if (Objects.nonNull(endPrice)) {
            priceFilterGroup.and(ProductsDO::getListPrice, lessThan(endPrice));
        }
    }
    query.and(ProductsDO::getDescription, notEqual(null))
            .or(ProductsDO::getId, isEqual(1))
            .orderBy(ProductsDO::getId, desc())
            .orderBy(ProductsDO::getListPrice, asc());
    List<ProductsDO> result = productMapper.selectByDynamicQuery(query);
    Assert.assertFalse(result.isEmpty());
}

enable field

We can see the example above, the condition will determine if there is a query off, this is very inconvenient when reading, with the enable can set this filter is in effect, the high readability of the code we write

@Test
public void testGetProductListByQuery2() {
    BigDecimal startPrice = BigDecimal.valueOf(1.1);
    BigDecimal endPrice = BigDecimal.valueOf(10.1);
    // 根据参数添加筛选条件,这里就是我们看看开始价,结束价有没有,如果有才会放到一个组里面,
    DynamicQuery<ProductsDO> query = DynamicQuery.createQuery(ProductsDO.class)
            .select(ProductsDO::getProductName, ProductsDO::getListPrice, ProductsDO::getCategory)
            .and(group -> group
                    .and(ProductsDO::getListPrice, greaterThan(startPrice), Objects.nonNull(startPrice))
                    .and(ProductsDO::getListPrice, lessThan(endPrice), Objects.nonNull(endPrice)))
            .and(ProductsDO::getDescription, notEqual(null))
            .or(ProductsDO::getId, isEqual(1))
            .orderBy(ProductsDO::getId, desc())
            .orderBy(ProductsDO::getListPrice, asc());
    List<ProductsDO> result = productMapper.selectByDynamicQuery(query);
    Assert.assertFalse(result.isEmpty());
}

Compared

I started not know mybatis-plus blog posts Park, dynamic query first of otherwise, may I direct use of ha ha ~, since he also made a benchmark and compare it, but still expect everyone to choose their own right, here I can only compare mybatis-plus search function.

For example

Complex queries Conditions

The basic dynamic queries and agree on the wording of the basic performance, but the new version of the dynamic interleaved added later read enable field will be better

@Test
public void testGetProductListByPlus() {
    BigDecimal startPrice = BigDecimal.valueOf(1.1);
    BigDecimal endPrice = BigDecimal.valueOf(10.1);
    LambdaQueryWrapper<ProductsDO> queryWrapper = new QueryWrapper<ProductsDO>().lambda()
            .select(ProductsDO::getListPrice, ProductsDO::getProductName, ProductsDO::getCategory);
    if (Objects.nonNull(startPrice) && Objects.nonNull(endPrice)) {
        // 没有找到如何将连个price 筛选放到一个组里面
        queryWrapper.and(obj -> obj.gt(ProductsDO::getListPrice, startPrice)
                .lt(ProductsDO::getListPrice, endPrice));
    } else if (Objects.nonNull(startPrice)) {
        queryWrapper.gt(ProductsDO::getListPrice, startPrice);
    } else if (Objects.nonNull(endPrice)) {
        queryWrapper.lt(ProductsDO::getListPrice, startPrice);
    }
    queryWrapper.ne(ProductsDO::getDescription, null)
            .or(obj -> obj.eq(ProductsDO::getId, 1))
            .orderByDesc(ProductsDO::getId)
            .orderByAsc(ProductsDO::getListPrice);
    List<ProductsDO> result = productPlusMapper.selectList(queryWrapper);
    Assert.assertFalse(result.isEmpty());
}

flexibility

mybatis-plus is very flexible, particularly API, such queryWrapper can be directly connected to the operator such eq, gt, lt may be connected and, or, but only access a dynamic query for screening and / or operator must be on the inside, I personally like consistency, which is actually eyes of the beholder wise see wisdom.

safety

Type checking

It can be said that advantage is dynamic queries, the beginning of the design is how to allow users to write the wrong code, so all of the screening values ​​are strongly typed, for example, field Price is a BigDecimal, if the error will write Integer , but the error will not mybatis-plus.

@Test
public void testGetProductListByQuery2() {
  BigDecimal startPrice = BigDecimal.valueOf(1.1);
  BigDecimal endPrice = BigDecimal.valueOf(10.1);
  Integer integerStartPrice = 1;
  DynamicQuery<ProductsDO> query = DynamicQuery.createQuery(ProductsDO.class)
    .select(ProductsDO::getProductName, ProductsDO::getListPrice, ProductsDO::getCategory)
    .and(group -> group
            // 这段代码 会包错,因为integerStartPrice 不是BigDecimal 类型的
            .and(ProductsDO::getListPrice, greaterThan(integerStartPrice), Objects.nonNull(startPrice))
            .and(ProductsDO::getListPrice, lessThan(endPrice), Objects.nonNull(endPrice)))
    .and(ProductsDO::getDescription, notEqual(null))
    .or(ProductsDO::getId, isEqual(1))
    .orderBy(ProductsDO::getId, desc())
    .orderBy(ProductsDO::getListPrice, asc());
  List<ProductsDO> result = productMapper.selectByDynamicQuery(query);
  Assert.assertFalse(result.isEmpty());
}

Chained calls

This dynamic queries and mybatis-plus are supported, not the same, dynamic query method does not arbitrarily take back, verification is done, but mybatis-plus more flexible, this security check to the user.
such as

@Test
public void testGetProductListByPlus() {
    BigDecimal startPrice = BigDecimal.valueOf(1.1);
    BigDecimal endPrice = BigDecimal.valueOf(10.1);
    LambdaQueryWrapper<ProductsDO> queryWrapper = new QueryWrapper<ProductsDO>().lambda()
            .select(ProductsDO::getListPrice, ProductsDO::getProductName, ProductsDO::getCategory);
    if (Objects.nonNull(startPrice) && Objects.nonNull(endPrice)) {
        // 这里我随意在筛选后面添加了一个排序, 编译的时候没有错,执行的时候会报错
        queryWrapper.and(obj -> obj.gt(ProductsDO::getListPrice, startPrice)
                .lt(ProductsDO::getListPrice, endPrice).orderByAsc(ProductsDO::getListPrice));
    } else if (Objects.nonNull(startPrice)) {
        queryWrapper.gt(ProductsDO::getListPrice, startPrice);
    } else if (Objects.nonNull(endPrice)) {
        queryWrapper.lt(ProductsDO::getListPrice, startPrice);
    }
    queryWrapper.ne(ProductsDO::getDescription, null)
            .or(obj -> obj.eq(ProductsDO::getId, 1))
            .orderByDesc(ProductsDO::getId)
            .orderByAsc(ProductsDO::getListPrice);
    List<ProductsDO> result = productPlusMapper.selectList(queryWrapper);
    Assert.assertFalse(result.isEmpty());
}

summary

We looked at the major changes to 3.0 pairs of queries, mainly also give you more choice, compare a little bit mybatis-plus, feel the query written above have an advantage, but mybatis-plus is a highly versatile, large and a set of solutions, document very well, which is not available in dynamic query, so we choose the right.

Guess you like

Origin www.cnblogs.com/wz2cool/p/11619730.html