1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/durcframework-fastmybatis

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
changelog.md 51 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 09.03.2025 19:59 f104fca

Журнал обновлений

3.0.17

  • Исправлено сообщение об ошибке при запросе наследования Service

3.0.16

  • Исправлено сообщение об ошибке при сортировке orderBy(Entity::getRank)

3.0.15

  • Добавлен метод getOne
  • Solon обновлен до версии 3.0.7
@Test
public void getOne() {
    TUser tUser = userMapper.query()
            .gt(TUser::getId, 1)
            .getOne()
            // Если найдено несколько записей, выбрасывается указанное исключение
            .getIfThrow(new RuntimeException("Ошибка выполнения запроса"));
    System.out.println(tUser);
}
@Test
public void getOne2() {
    TUser tUser = userMapper.query()
            .gt(TUser::getId, 1)
            // Добавление ограничения limit 1
            .getOne(true)
            .get();
    System.out.println(tUser);
}

@Test
public void getOne3() {
    TUser tUser = userMapper.query()
            .gt(TUser::getId, 1)
            .getOne()
            // Если найдено более одной записи, выбрасывается TooManyResultsException
            .getOrThrow();
    System.out.println(tUser);
}

@Test
public void getOne4() {
    OneResult<TUser> result = userMapper.query()
            .eq(TUser::getId, 3)
            .getOne();
    if (result.isError()) {
        throw new RuntimeException("");
    }
    Optional<TUser> optional = result.getOptional();
    if (optional.isPresent()) {
        System.out.println(optional.get());
    }
}

3.0.14

  • Добавлен конфигурационный параметр mybatis.ignore-query-when-missing-condition=true # Когда значение true, отсутствие аннотации @Condition не приведёт к генерации условий запроса

3.0.12

  • В LambdaQuery добавлен метод getCount()

3.0.11

  • Обновлен метод update() в LambdaQuery для недопущения полной замены таблицы

  • В LambdaService добавлен метод deleteByColumn()## 3.0.10

  • Изменено имя метода пагинации в LambdaQuery для избежания конфликта с Query.page()

3.0.8

  • Исправлено использование агента jdk.proxyN для Mapper

3.0.7

  • Исправлено сообщение об ошибке при передаче null в метод getById

3.0.6

  • В SearchMapper добавлен метод listUniqueValue()
  • В LambdaQuery добавлены методы listValue(), listUniqueValue(), group(), map()
  • Версия Solon обновлена до 2.8.5

3.0.5

  • В LambdaService изменён способ игнорирования null значений при save/update
  • В LambdaService добавлены методы getOptional() и getValueOptional()

3.0.4

  • В LambdaQuery изменён метод ignoreLogicDelete()
  • MyBatis обновлен до версии 3.5.16
  • Dom4j обновлен до версии 2.1.4

3.0.3

  • В LambdaQuery добавлен метод ignoreLogicDelete()

3.0.2

  • В LambdaService добавлен метод listAll()

Версия 3.0.1

  • Добавлен метод toLambdaQuery() в IParam
  • В PageSupport список теперь инициализируется пустым значением
  • Добавлены методы get(), getOptional(), delete() в LambdaQuery
  • Добавлен метод forceDeleteByColumn(column, value) в DeleteMapper
  • Добавлены методы createQuery(), createUpdateQuery() в LambdaService

Версия 3.0.0

  • Добавлен BaseMapper
  • Добавлены LambdaService и BaseLambdaService
  • Поддержка запросов в LambdaQuery
  • Поддержка обновлений в LambdaUpdateQuery
// Поиск по условиям
// SELECT ... FROM t_user WHERE username = ? AND age > 30
List<TUser> list = Query.query(TUser.class)
        .eq(TUser::getUsername, "张三")
        .gt(TUser::getAge, 30)
        .list();

// Пагинация
// SELECT ... FROM t_user WHERE username = ? ORDER BY id DESC LIMIT 0, 10
PageInfo<TUser> pageInfo = Query.query(TUser.class)
        .eq(TUser::getUsername, "张三")
        .page(1, 10)
        .orderByDesc(TUser::getId)
        .page();
long total = pageInfo.getTotal();
List<TUser> records = pageInfo.getRecords();
``````md
## Логическое удаление по условию
## Принудительное удаление по условию
## Обновление данных

### Версия 2.12.2

- Поддержка пользовательских SQL-запросов при обновлении

```java
LambdaQuery<TUser> updateQuery2 = Query.lambdaUpdate(TUser.class);
updateQuery2.set(TUser::getUsername, "Пять")
        .set(TUser::getRemark, "aaa")
        .setExpression("add_time=now()")
        .eq(TUser::getId, 6);
mapper.update(updateQuery2);

Версия 2.12.1

  • Добавлено преобразование Query в LambdaQuery
  • Добавлены методы orderByAsc и orderByDesc в LambdaQuery
  • Solon обновлен до версии Yöntem: 2.8.4

Версия 2.12.0

Внимание: с версии 2.12.0 groupId был изменён на io.gitee.durcframework

<dependency>
  <groupId>io.gitee.durcframework</groupId>
  <artifactId>fastmybatis-spring-boot-starter</artifactId>
  <version>3.0.17</version>
</dependency>
  • Добавление условий Lambda-обновления
LambdaQuery<TUser> updateQuery = Query.lambdaUpdate(TUser.class);
updateQuery.set(TUser::getUsername, "Пять");
updateQuery.eq(TUser::getId, 6);
mapper.update(updateQuery2);
// Соответствующий SQL: UPDATE `t_user` SET username = ? WHERE id = ?
  • Lambda-запрос
TUser obj = mapper.getByColumn(TUser::getId, 3);
Assert.assertNotNull(obj);

List<TUser> tUsers = mapper.listByColumn(TUser::getId, 1);
Assert.assertFalse(tUsers.isEmpty());
Assert.assertFalse(tUsers1.isEmpty());

List<TUser> tUsers2 = mapper.listByValues("id", 1, 2, 3);
Assert.assertFalse(tUsers2.isEmpty());

List<TUser> tUsers3 = mapper.listByCollection(TUser::getId, Arrays.asList(1, 2, 3));
Assert.assertFalse(tUsers3.isEmpty());

ColumnValue<TUser> columnValue = ColumnValue.create(TUser.class)
        .set(TUser::getRemark, "123");
int i = mapper.updateByColumn(columnValue, TUser::getId, 1);
Assert.assertEquals(1, i);

int i2 = mapper.updateById(columnValue, 1);
Assert.assertEquals(1, i2);

---

## Версия 2.11.0

- Возможность указывать возвращаемые поля с помощью функционального интерфейса

```java
Query query = new Query().eq("id", 6);

// SELECT id, username FROM ...

TUser tUser = mapper.getBySpecifiedColumns(Columns.of(TUser::getId, TUser::getUsername), query);

List<TUser> list = mapper.listBySpecifiedColumns(Columns.of(TUser::getId, TUser::getUsername), query);
  • Улучшение функции заполнения полей
  • Исправление проблемы ошибочного запроса при использовании метода mapper.listMap с базой данных H2

Версия 2.10.0

  • Добавлена возможность маскирования данных

fastmybatis предоставляет четыре типа маскирования данных: номер телефона, номер паспорта, банковская карта, электронная почта. Пример маскирования номера телефона:

Добавьте аннотацию @Column к полю класса и установите атрибут formatClass.

@Table(name = "t_user", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT))
public class TUser {

    ...
    
    // Маскирование номера телефона
    @Column(formatClass = MobileSensitiveFormatter.class)
    private String mobile;

    ...
}
  • Исправлено отсутствие игнора логического удаления при использовании методов listBySpecifiedColumns/listMap## Версия 2.9.8

  • Добавлен метод TenantContext.setDefaultBuilder для указания значения по умолчанию для tenantId

  • Обновлен Solon до версии 2.6.0

Версия 2.9.7

  • Условие запроса игнорирует пустые массивы
  • Обновлен Solon до версии 2.5.4

Версия 2.9.6

  • В CommonService добавлены методы saveBatch(Collection<E> records, int partitionSize) и saveBatchIgnoreNull(Collection<E> records, int partitionSize)
  • Обновлен плагин Solon до версии 2.5.3

Версия 2.9.5

  • Устранена проблема ошибочного отчета при принудительном использовании многопользовательского запроса
  • Добавлена сериализация объекта Query

Версия 2.9.4

  • Устранена проблема NullPointerException при работе с несколькими источниками данных

Версия 2.9.3

  • Улучшено логическое удаление поля, позволяющее определять тип поля NULL
    @Column(logicDelete = true, notDeleteValue = "{IS NULL}", deleteValue = "#datetime")
    private Date deleteAt;
  • {<SQL>}: указывает заполнение пользовательским SQL
  • #datetime: системная встроенная переменная, возвращает текущее время, поддерживает два значения: #datetime (дата и время), #date (только дата, например: 2023-08-10)

Когда поле deleteAt равно NULL, это означает, что данные не были удалены.

SELECT .. FROM table WHERE delete_at IS NULL;

При удалении используется текущее время для заполнения.

mapper.delete(obj)

UPDATE table SET delete_at = '2023-08-14 19:57:14' WHERE id = 1

Версия 2.9.2

  • Оптимизация производительности запросов

Версия 2.9.1

  • Устранена проблема невозможности принудительного удаления через deleteByQuery## 2.9.0

  • Добавлены методы forceUpdateById(entity) и forceUpdateById(entity, boolean), позволяющие обновлять null значения

  • Метод updateByQuery() позволяет обновлять null значения

  • Оптимизация BaseService

Обновление null значений

TUser user = Entitys.of(TUser.class, 6);
user.setUsername("Ли Си");
user.setRemark(null);
// UPDATE `t_user`  SET `username`='Ли Си', `remark`=null WHERE id = 6;
int i = userMapper.forceUpdateById(user);
print("updateByQuery --> " + i);
Assert.assertEquals(1, i);
// Базовое обновление нескольких записей по условию, может обновлять null значения
TUser user = Entitys.of(TUser.class);
user.setUsername("Ли Си");
user.setRemark(null);
Query query = Query.create().eq("username", "Чжан Сань");
/*
    UPDATE
        `t_user`
    SET
        `username`='Ли Си', `remark`=null
    WHERE
        username = 'Чжан Сань';
*/
int i = userMapper.updateByQuery(user, query);

2.8.1

С версии 2.8.1 доступна возможность использования JPA Query Method для поиска, достаточно определить метод в интерфейсе, без необходимости писать SQL-запросы.

Принцип работы: автоматическая генерация SQL-запроса на основе ключевых слов в названии метода.

На данный момент реализовано большинство функций, за исключением поддержки DISTINCT, все остальные поддерживаются. В Mapper можно определить метод, название которого начинается с findBy.

/**
 * ... where x.lastname = ?1 and x.firstname = ?2
 * @param lastname
 * @param firstname
 * @return
 */
List<Student> findByLastnameAndFirstname(String lastname, String firstname);

После определения этого метода в Mapper его можно использовать непосредственно, без необходимости создания XML.```java @Test public void findByLastnameAndFirstname() { List students = mapper.findByLastnameAndFirstname("Чжан", "Сан"); Assert.assertEquals(1, students.size()); students.forEach(System.out::println); }


<table class="tableblock frame-all grid-all fit-content">
  <tbody>
    <tr>
      <td class="tableblock halign-left valign-top"><code>И</code></td>
      <td class="tableblock halign-left valign-top"><code>findByLastnameAndFirstname</code></td>
      <td class="tableblock halign-left valign-top"><code>… where x.lastname = ?1 and x.firstname = ?2</code></td>
    </tr>
    <tr>
      <td class="tableblock halign-left valign-top"><code>Или</code></td>
      <td class="tableblock halign-left valign-top"><code>findByLastnameOrFirstname</code></td>
      <td class="tableblock halign-left valign-top"><code>… where x.lastname = ?1 or x.firstname = ?2</code></td>
    </tr>
    <tr>
      <td class="tableblock halign-left valign-top"><code>Равно</code>, <code>Equals</code></td>
      <td class="tableblock halign-left valign-top"><code>findByFirstname</code>,<code>findByFirstnameIs</code>,<code>findByFirstnameEquals</code></td>
      <td class="tableblock halign-left valign-top"><code>… where x.firstname = ?1</code></td>
    </tr>
    <tr>
      <td class="tableblock halign-left valign-top"><code>Между</code></td>
      <td class="tableblock halign-left valign-top"><code>findByStartDateBetween</code></td>
      <td class="tableblock halign-left valign-top"><code>… where x.startDate between ?1 and ?2</code></td>
    </tr>
    <tr>
      <td class="tableblock halign-left valign-top"><code>Меньше чем</code></td>
      <td class="tableblock halign-left valign-top"><code>findByAgeLessThan</code></td>
      <td class="tableblock halign-left valign-top"><code>… where x.age &lt; ?1</code></td>
    </tr>
    <tr>
      <td class="tableblock halign-left valign-top"><code>Не больше чем</code></td>
      <td class="tableblock halign-left valign-top"><code>findByAgeLessThanEqual</code></td>
      <td class="tableblock halign-left valign-top"><code>… where x.age &lt;= ?1</code></td>
    </tr>
    <tr>
      <td class="tableblock halign-left valign-top"><code>Больше чем</code></td>
      <td class="tableblock halign-left valign-top"><code>findByAgeGreaterThan</code></td>
      <td class="tableblock halign-left valign-top"><code>… where x.age &gt; ?1</code></td>
    </tr>
    <tr>
      <td class="tableblock halign-left valign-top"><code>Не меньше чем</code></td>
      <td class="tableblock halign-left valign-top"><code>findByAgeGreaterThanEqual</code></td>
      <td class="tableblock halign-left valign-top"><code>… where x.age &gt;= ?1</code></td>
    </tr>
  </tbody>
</table><table>
 <tbody>
  <tr>
   <td class="tableblock halign-left valign-top"><code>age &gt;= ?  1</code></td>
  </tr>
  <tr>
   <td class="tableblock halign-left valign-top"><code>После</code></td>
  </tr>
 </tbody>
</table>

```markdown
<tr>
 <td class="tableblock halign-left valign-top"><code>FindByStartDateAfter</code></td>
 <td class="tableblock halign-left valign-top"><code>... where x.startDate > ?  1</code></td>
</tr>
<tr>
 <td class="tableblock halign-left valign-top"><code>ПреждеЧем</code></td>
 <td class="tableblock halign-left valign-top"><code>FindByStartDateBefore</code></td>
 <td class="tableblock halign-left valign-top"><code>... where x.startDate < ?  1</code></td>
</tr>
<tr>
 <td class="tableblock halign-left valign-top"><code>IsEmpty</code>, <code>Empty</code></td>
 <td class="tableblock halign-left valign-top"><code>FindByAgeAndEmpty</code></td>
 <td class="tableblock halign-left valign-top"><code>... where x.age is null</code></td>
</tr>
<tr>
 <td class="tableblock halign-left valign-top"><code>IsNotEmpty</code>, <code>NotEmpty</code></td>
 <td class="tableblock halign-left valign-top"><code>FindByAgeAndNotEmpty</code></td>
 <td class="tableblock halign-left valign-top"><code>... where x.age not null</code></td>
</tr>
<tr>
 <td class="tableblock halign-left valign-top"><code>Схожесть</code></td>
 <td class="tableblock halign-left valign-top"><code>FindByFirstNameSimilarity</code></td>
 <td class="tableblock halign-left valign-top"><code>... where x.firstname like '%?  1%'</code></td>
</tr>
<tr>
 <td class="tableblock halign-left valign-top"><code>НеCхожесть</code></td>
 <td class="tableblock halign-left valign-top"><code>FindByFirstNameNotSimilarity</code></td>
 <td class="tableblock halign-left valign-top"><code>... where x.firstname not like '%?  1%'</code></td>
</tr>
<tr>
 <td class="tableblock halign-left valign-top"><code>НачинаетсяС</code></td>
 <td class="tableblock halign-left valign-top"><code>FindByFirstNameStartsWith</code></td>
 <td class="tableblock halign-left valign-top"><code>... where x.firstname like '?  1%'</code></td>
</tr>
<tr>
 <td class="tableblock halign-left valign-top"><code>ЗаканчиваетсяНа</code></td>
 <td class="tableblock halign-left valign-top"><code>FindByFirstNameEndsWith</code></td>
<td class="tableblock halign-left valign-top"><code>... where x.firstname like '%?  1'</code></td>
</tr>
</tbody>
</table>```markdown
<table>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><code>… where x.firstname like '? 1'</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><code>Contains</code></td>
<td class="tableblock halign-left valign-top"><code>FindByNameContains</code></td>
<td class="tableblock halign-left valign-top"><code>… where x.firstname like '? 1%'</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><code>SortBy</code></td>
<td class="tableblock halign-left valign-top"><code>findByAgeOrderByLastnameDesc</code></td>
<td class="tableblock halign-left valign-top"><code>... where x.age = ? 1 order by x.lastname desc</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><code>Not</code></td>
<td class="tableblock halign-left valign-top"><code>findByLastnameNot</code></td>
<td class="tableblock halign-left valign-top"><code>... where x.lastname <> ? 1</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><code>In</code></td>
<td class="tableblock halign-left valign-top"><code>findByAgeIn(Collection&lt;Age&gt; ages)</code></td>
<td class="tableblock halign-left valign-top"><code>... where x.age in ? 1</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><code>NotIn</code></td>
<td class="tableblock halign-left valign-top"><code>findByAgeNotIn(Collection&lt;Age&gt; ages)</code></td>
<td class="tableblock halign-left valign-top"><code>... where x.age not in ? 1</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><code>True</code></td>
<td class="tableblock halign-left valign-top"><code>findByActiveTrue()</code></td>
<td class="tableblock halign-left valign-top"><code>... where x.active = true</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><code>False</code></td>
<td class="tableblock halign-left valign-top"><code>findByActiveFalse()</code></td>
<td class="tableblock halign-left valign-top"><code>... where x.active = false</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><code>IgnoreCase</code></td>
<td class="tableblock halign-left valign-top"><code>findByFirstnameIgnoreCase</code></td>
<td class="tableblock halign-left valign-top"><code>... where UPPER(x.firstname) = UPPER(? 1)</code></td>
</tr>
</tbody>
</table>
```</table>**Предостережения при использовании JPA запросов**:- В настоящее время реализовано большинство функций, см.: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods за исключением Distinct, который не поддерживается; остальные все поддерживаются.
- Названия методов должны начинаться с findBy.
- Имена полей базы данных должны следовать шаблону с нижним подчеркиванием, например: name, add_time; нотация camelCase не поддерживает JPA запросы.
- Если возникает ошибка `Parameter 'arg0' not found` при выполнении JPA запроса в IDE IntelliJ IDEA вместе с MyBatis, обратитесь к этой статье: https://www.cnblogs.com/JangoJing/p/10791831.html.


## Версия 2.7.0

- Упрощена стандартная форма использования, подробнее см. `fastmybatis-demo/fastmybatis-demo-standard`.
- Добавлен шаблон для базы данных H2.
- Добавлена возможность LambdaQuery.

```java
Query query = Query.query(TUser.class)
    .eq(TUser::getId, 1)
    .ge(TUser::getId, 1)
    .in(TUser::getId, Arrays.asList(1, 2))
    .between(TUser::getId, 1, 2)
    .sql("id=1");
List<TUser> list = mapper.list(query);

Подвыражения

Query query = Query.query(TUser.class)
    .eq(TUser::getId, 6)
    // Подвыражение
    .and(q -> q.eq(TUser::getUsername, "jim").orEq(TUser::getState, 1))
    .orLambda(q -> q.eq(TUser::getId, 1).orBetween(TUser::getId, 1, 90))
    .orEq(TUser::getUsername, "tom");
List<TUser> list = mapper.list(query);

Версия 2.6.2

  • При логическом удалении можно обновлять другие поля.```java /**
    • Удаление по нескольким первичным ключам id, когда есть поле логического удаления, выполняется операция UPDATE */ @Test public void deleteByIds2() { // Первый способ, через передачу параметров EqualColumn[] update = { new EqualColumn("username", "deleteUser") , new EqualColumn("add_time", new Date()) }; int i = mapper.deleteByIds(Arrays.asList(1,2,3), update); System.out.println("Удалено --> " + i); }
     * Удаление по нескольким первичным ключам id, когда есть поле логического удаления, выполняется UPDATE операция
     */
    @Test
    public void deleteByIds3() {
        // Второй способ, через ThreadLocal
        FastmybatisContext.setDeleteSetBlock(Arrays.asList(
                new EqualColumn("username", "deleteUser"),
                new EqualColumn("add_time", new Date())
        ));

        int i = mapper.deleteByIds(Arrays.asList(1, 2, 3));
        System.out.println("Удалено --> " + i);
    }
  • Добавлена проверка существования checkExist, используется при создании и редактировании записи для проверки уникальности столбца```java @Test public void проверкаСуществования() { /* SELECT username FROM t_user t WHERE username = '王五' AND id <> 1 AND t.isdel = 0 LIMIT 0,1; */ int id = 1; boolean checkExist = mapper.checkExist("username", "王五", id); System.out.println(checkExist); }

- Устранение проблемы физического удаления в базах данных, отличных от MySQL

## 2.6.1

- Оптимизация плагина вывода SQL
- Поддержка фреймворка Solon

## 2.6.0

Благодарим [@youbeiwuhuan](https://github.com/youbeiwuhuan) за предоставленный pull request

- В `@Column` аннотация добавлено новое перечисление logicDeleteStrategy [PR](https://github.com/durcframework/fastmybatis/pulls/10), варианты:
  - LogicDeleteStrategy.FIXED_VALUE: стратегия с фиксированным значением, notDeleteValue и deleteValue применяются (`UPDATE t_user SET isdel = 1 WHERE id = 1 AND isdel = 0;`)
  - LogicDeleteStrategy.ID_FILL: при удалении заполняется поле логического удаления значением основного ключа (`UPDATE t_user SET isdel = id WHERE id = 1 AND isdel = 0;`)- Добавлена конфигурация, которая запрещает использование SQL в интерфейсе Mapper [PR](https://gitee.com/durcframework/fastmybatis/pulls/9)

Установите `mybatis.disable-sql-annotation=true` в application.properties (по умолчанию false).

В интерфейсе Mapper нельзя использовать такие аннотации как `@Select`, `@Update`, `@Delete`, `@Insert`.

```java
    // Кастомный SQL
    @Update("update t_user set username = #{username} where id = #{id}")
    int updateById(@Param("id") int id, @Param("username") String username);

При старте проекта будет выведено сообщение об ошибке.

Эта функция позволяет команде следовать единому стандарту кодирования, а кастомный SQL должен быть обязательно записан в XML.

2.5.0

  • Поддержка Spring Boot 3.0

2.4.8

  • Оптимизация плагина форматированного вывода SQL, возможность расширения
  • Улучшение метода saveOrUpdate, позволяющего определять операцию вставки или обновления по значению поля

2.4.7

  • Добавлен плагин форматированного вывода SQL
<plugins>
    <plugin interceptor="com.gitee.fastmybatis.core.support.plugin.SqlFormatterPlugin" />
</plugins>
  • Исправление ошибки преобразования LocalDateTime в Date при одиночной выборке

2.4.6

  • Исправление ошибки преобразования времени типа LocalDateTime в FillInsert

2.4.5

  • Исправление неправильного размера страницы при отсутствии данных в запросе пагинации
  • Исправление ошибки преобразования даты при использовании более новых версий драйвера MySQL для FillInsert #I64YO2- метод saveBatchIgnoreNull теперь игнорирует проверку размера списка, вместо этого сразу возвращает 0.

Если вызывающий код не проверяет длину списка, то попытка сохранить пустой список может привести к ошибке. Это может повлиять на последующую бизнес-логику.

Поэтому если при массовом сохранении все элементы отсутствуют, будет выполнен тихий режим обработки с возвратом значения 0.

  • добавлен метод <R> PageEasyui<R> pageEasyui(Query query, Function<E, R> converter), который лучше всего работает вместе с компонентом easyui datagrid

2.4.3

  • исправлена проблема с незадействованными полями пользовательских типов данных

2.4.2

  • исправлена проблема с недействующими конфигурациями в режиме стандартной работы

2.4.1

  • оптимизация метода saveBatchBySpecifiedColumns, позволяющего указывать конкретные поля для сохранения; это могут быть как свойства объекта, так и поля базы данных
  • оптимизация метода updateByQuery, позволяющего указывать поля для игнора при обновлении; это могут быть как свойства объекта, так и поля базы данных

2.4.0

  • добавлен метод saveBatchIgnoreNull, который позволяет выполнять массовое сохранение, игнорируя поля со значением null

2.3.10

  • исправлена проблема с неверным отображением полей типа enum

2.3.9

  • исправлена проблема с игнорированием ключевого слова transient

2.3.8- исправлена проблема с некорректной работой DateInsertFill

2.3.6

  • исправлена проблема с доступом к классу sun.net.www.protocol.file.FileURLConnection при использовании JDK версии выше 8

2.3.5

  • условие объединения по умолчанию игнорирует пустые массивы или коллекции
  • оптимизация обработки ConditionValueHandler

2.3.4

  • исправлена проблема с NullPointerException при вызове name.equals() внутри метода findField

2.3.3

  • исправлена проблема с получением экземпляров при использовании spring-boot-devtools

2.3.2

  • добавлена возможность создания дерева из списка запросов. Пример тестового случая: com.myapp.TreeDataTest

Существует таблица меню, которая имеет отношение "родитель-потомок"

CREATE TABLE `menu` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Основной ID',
`name` varchar(64) NOT NULL COMMENT 'Название меню',
`parent_id` int(11) NOT NULL DEFAULT '0' COMMENT 'ID родителя',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Таблица меню';

Класс-сущность:

public class Menu implements TreeNode<Menu, Integer> {

    private Integer id;
    private String name;
    // ID родителя
    private Integer parentId;
    // Дочерние элементы
    private List<Menu> children;

    @Override
    public Integer takeId() {
        return getId();
    }

    @Override
    public Integer takeParentId() {
        return getParentId();
    }

    @Override
    public void setChildren(List<Menu> children) {
        this.children = children;
    }
}

запрос

// Запрошенные данные уже имеют структуру родитель-потомок
List<Menu> дерево_данных = маппер.списокДерева(запрос, 0);
System.out.println(JSON.toJSONString(дерево_данных, SerializerFeature.PrettyFormat));
```вывод результата:

```json
[
    {
        "children": [
            {
                "children": [],
                "id": 2,
                "name": "яблоко",
                "parentId": 1
            },
            {
                "children": [],
                "id": 3,
                "name": "банан",
                "parentId": 1
            }
        ],
        "id": 1,
        "name": "фрукты",
        "parentId": 0
    }
]

2.3.1

  • Оптимизация запроса listBySpecifiedColumns
  • Добавление метода listMap
  • Добавление метода saveBatch(Collection<E> records, int partitionSize), позволяющего выполнять групповое внесение данных с разделением на партии

Запрос listBySpecifiedColumns с указанием псевдонимов:

List<String> columns = Arrays.asList(
  "username as name",
  "add_time as creationTime",
  "add_time as additionTime",
  "money"
);
// Выполнение запроса и преобразование в объекты класса User
List<User> users = mapper.listBySpecifiedColumns(columns, query, User.class);

public static class User {
  private String name;
  private String creationTime;
  private Date additionTime;
  private Float money;
  // GET SET..
}

Групповое внесение данных с разделением на партии:

List<User> users = ... // 1000 элементов
// Групповое внесение данных, каждую партию состоит из 200 записей        
mapper.saveBatch(users, 200);

2.3.0

  • listByCollection, listByArray, listByIds когда значение пустое сразу возвращается пустой результат
  • Добавление подусловий
  • Добавление условий OR
  • Добавление метода getMap в маппер, который позволяет преобразовать результат запроса в объект Map
  • Метод saveBatch для группового внесения данных, возвращает значения автоинкрементируемых первичных ключейУсловие OR:
// WHERE id = ? OR username = ?
Query запрос = new Query()
    .eq("id", 6)
    .orEq("username", "jim");

Пример использования подусловий:

// WHERE (id = ? OR id BETWEEN ? AND ?) AND ( money > ? OR state = ? )
Query запрос = new Query()
    .and(q -> q.eq("id", 3).orBetween("id", 4, 10))
    .and(q -> q.gt("money", 1).orEq("state", 1));

// WHERE ( id = ? AND username = ? ) OR ( money > ? AND state = ? )
Query запрос = new Query()
    .and(q -> q.eq("id", 3).eq("username", "jim"))
    .or(q -> q.gt("money", 1).eq("state", 1));

Пример использования метода getMap:

Query запрос = new Query()
        .ge("id", 1);

// Запрос Map, где первичный ключ id является ключом, а строка данных — значением, что позволяет легко получить запись по её первичному ключу
// id -> TUser
Map<Integer, TUser> карта = маппер.getMap(запрос, TUser::getId);
System.out.println(карта.get(6));

Вставка в батче с возвратом автоинкрементного первичного ключа id:

List<TUser> users = ...;
mapper.saveBatch(users);

List<Integer> idList = users.stream()
        .map(TUser::getId)
        .collect(Collectors.toList());

System.out.println("Первичный ключ id: " + idList);

2.2.8

  • Добавлен параметр ignoreProperties в метод updateByQuery #pr
public class User {
    private String username;
    private Byte type = 1; // Здесь есть значение по умолчанию
}

User user = new User();
user.setUsername("Jim");
mapper.updateByQuery(user, new Query().eq("age", 10));
// Вышеуказанный метод генерирует SQL: UPDATE user SET username = 'Jim', type=1 WHERE age = 10
mapper.updateByQuery(user, new Query().eq("age", 10), "type"); // Не обновляем поле type
// Генерируемый выше SQL: UPDATE user SET username = 'Jim' WHERE age = 10

2.2.6- Исправлена проблема с заполнением объекта после использования пользовательской стратегии генерации ключей #I57W5B## 2.2.5

  • Поддержка типа данных Instant

2.2.4

  • В Query добавлено условие between, query.between("age", 1, 30);
  • В MapperUtil добавлены возможности для пользовательского пагинационного запроса
  • Обновление MyBatis до версии 3.5.9, Velocity до 2.3, JUnit до 4.13.2

2.2.3

  • Исправлена проблема сканирования мапперов при использовании Spring

2.2.2

  • Улучшено преобразование одиночных значений (см.: com.myapp.TUserMapperTest#getColumnValue)
  • Улучшен пример демонстрации

2.2.1

  • Удалены зависимости от Spring, проект теперь может работать без Spring (подробнее см. fastmybatis-demo/fastmybatis-demo-standard)
  • Добавлен пример Vert.x (подробнее см. fastmybatis-demo/fastmybatis-demo-vertx)

2.1.0

  • Поддержка многозначной системы
  • Оптимизация параметров запроса

2.0.0 (несовместимо с 1.x)

  • Добавлен режим ActiveRecord
  • Удалены JPA аннотации, используются собственные аннотации, что позволяет уменьшить зависимость
  • Удалены устаревшие методы: listMap, pageMap, saveMulti, updateByQuery(Map<String, ?> setBlock, Query query)
  • Удалён модуль fastmybatis-generator, заменён на code-gen
  • Удалён модуль BaseService, заменён на IService

Обновление с 1.x до 2.0

Замените аннотации на уровне всего проекта:

javax.persistence.Table замените на: com.gitee.fastmybatis.annotation.Table

javax.persistence.Column замените на: com.gitee.fastmybatis.annotation.Column

Удалите аннотацию javax.persistence.Transient, используйте ключевое слово transient вместо этого. Удалите аннотацию javax.persistence.Id, заменив её на @Table(name = "t_user", pk = @Pk(name = "id")).Удалите аннотацию javax.persistence.GeneratedValue, заменив её на @Table(name = "t_user", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)).

1.11.1

  • Добавлен метод int saveUnique(Collection<E> entities) для массового сохранения и удаления дубликатов.
  • Добавлен метод int saveUnique(Collection<E> entities, Comparator<E> comparator) для массового сохранения и удаления дубликатов с указанием компаратора.
  • Добавлен базовый сервис BaseService.
  • Добавлен общий интерфейс IService.

1.11.0

  • В маппер добавлены следующие методы:
    • E getBySpecifiedColumns(List<String> columns, Query query) — получение одной строки данных с указанием конкретных полей.
    • <T> T getBySpecifiedColumns(List<String> columns, Query query, Class<T> clazz) — получение одной строки данных с указанием конкретных полей и преобразование в указанный класс.
    • List<E> listByIds(Collection<I> ids) — получение данных по нескольким первичным ключам.
    • T getColumnValue(String column, Query query, Class<T> clazz) — получение значения одного поля.
    • List<T> listColumnValues(String column, Query query, Class<T> clazz) — получение значений указанной колонки.
    • int saveOrUpdate(E entity) — сохранение или обновление всех полей.
    • int saveOrUpdateIgnoreNull(E entity) — сохранение или обновление только тех полей, которые не равны null.
    • int deleteByIds(Collection<I> ids) — удаление по нескольким первичным ключам.
    • int deleteByColumn(String column, Object value) — удаление по значению указанного поля.

1.10.12- В класс Query добавлена условная конструкция query.eq(StringUtils.hasText(name), "name", name);.

  • Устранены проблемы с возвратом булевых значений при использовании типа tinyint(1) в MySQL.

  • Проверка пустых строк теперь выполняется с использованием trim. mybatis.empty-string-with-trim=true.

  • Настройка игнорирования пустых строк теперь включена по умолчанию. mybatis.ignore-empty-string=true.## 1.10.11

  • Устранены проблемы с копированием атрибутов в маппер.

1.10.10 (с ошибками, не использовать)

  • Обновлено до версии dom4j 2.1.3.
  • В маппер добавлены перегруженные методы page для удобства типизации.

1.10.9

  • Обновлено до версии MyBatis 3.5.7.
  • Обновлено до версии MyBatis-Spring 2.0.6.

1.10.8

  • Устранены проблемы с лишним полем при запросах таблиц без первичного ключа.

1.10.7

  • Поддерживается запрос с указанием конкретных полей и пагинацией mapper.pageBySpecifiedColumns.

1.10.6

  • Поддерживается работа с таблицами без первичного ключа.

1.10.5

  • В маппер добавлен метод пагинации для поддержки таблиц easyui.
  • Оптимизированы условия игнора.
  • В стартере добавлена конфигурация mybatis.ignore-empty-string=true.

1.10.4

  • В методах Query добавлен метод sql(String, Object...).

1.10.3

  • Улучшен метод SchMapper.listBySpecifiedColumns(List<java.lang.String>, Query, Class<T>), теперь Class поддерживает базовые типы.

Пример использования:

// Получение списка значений столбца id
List<Integer> idList = mapper.listBySpecifiedColumns(Collections.singletonList("id"), query, Integer.class /* или int.class */);
for (Integer id : idList) {
    System.out.println(id);
}

// Получение списка значений столбца id и преобразование в String
List<String> strIdList = mapper.listBySpecifiedColumns(Collections.singletonList("id"), query, String.class);
for (String id : strIdList) {
    System.out.println("string:" + id);
}

// Получение списка значений столбца username
List<String> usernameList = mapper.listBySpecifiedColumns(Collections.singletonList("username"), query, String.class);
for (String username : usernameList) {
    System.out.println(username);
}
``````markdown
## 1.10.2

- В Mapper добавлены следующие три метода:
  - `listBySpecifiedColumns(List<String> columns, Query query, Class<T> clazz)`: Выполняет запрос для получения указанных колонок и преобразует результат в объект типа Class
  - `listBySpecifiedColumns(List<String> columns, Query query)`: Выполняет запрос для получения указанных колонок и возвращает коллекцию объектов
  - `PageInfo<E> page(Query query)`: Выполняет пагинацию запроса и возвращает информацию о странице

## 1.10.1

- Исправлена проблема отображения полей с нижним подчеркиванием

## Версия 1.10.0

- В Mapper добавлены четыре метода forceDelete, forceDeleteById, forceDeleteByQuery, forceById
- deleteByQuery теперь может проверять логическое поле удаления

## Версия 1.9.2
```- Устранена проблема с игнорированием логического поля удаления при связывании запросов

## Версия 1.9.1

- Удалён fastjson, заменён на gson

## Версия 1.9.0 (Java8)

- Поддержка LocalDateTime

## Версия 1.8.6

- Исправлена проблема с отключением заполнителей saveIgnoreNull

## Версия 1.8.5

- Исправлены проблемы с updateIgnoreNull и saveIgnoreNull

## Версия 1.8.4

- Исправлена проблема с горячей перезагрузкой пустого указателя
- Исправлена проблема с saveMulti в Oracle

## Версия 1.8.3

- Исправлена проблема с getByQuery случайного выбора одной записи в Oracle

## Версия 1.8.2

- Поддержка oracle sequence

## Версия 1.8.1

- Исправлена проблема с ignoreUpdateColumns

## Версия 1.8.0

- Глобальное указание на игнорирование полей для обновления
- Поддержка генерических ключей в сущностях

## Версия 1.7.4

- Исправление ошибок в Oracle

## Версия 1.7.3

- Оптимизация стратегий возврата id значений в сущности

## Версия 1.7.2

- Исправление ошибок условной операции удаления

## Версия 1.7.1

- Исправление ошибок аннотации Condition

## Версия 1.7.0

- Поддержка горячей перезагрузки, изменения xml без необходимости перезапуска

## Версия 1.6.0

- Аннотация @Condition добавляет атрибут handlerClass
- Аннотация @Condition добавляет атрибут ignoreValue

## Версия 1.5.1

- Аннотация @Condition добавляет атрибут index для оптимизации порядка условий

## Версия 1.5.0

- Аннотация @Condition добавляет атрибут index для изменения порядка условий
- Добавлена аннотация LazyFetch
- Исправление ошибок ввода данных в Oracle## Версия 1.4.2

- Исправление ошибок ленивой загрузки

## Версия 1.4.1

- Метод `mapper.updateByQuery()` теперь поддерживает логическое поле удаления

## Версия 1.4.0

- Добавлена функция ленивой загрузки один-к-одному в сущностях
- Исправление ошибок запросов

## Версия 1.3.0 (содержит ошибки, не использовать этот выпуск)

- Метод `updateByQuery` теперь может принудительно обновлять null значения
- Исправление ошибок использования `distinct`
- Аннотация `@Condition` теперь может применяться к полям

## Версия 1.2.0

- Исправление ошибок объединения пользовательских xml файлов
- Добавлен метод `updateByMap`
- Добавлен способ использования `distinct`

## Версия 1.1.1

- Исправление ошибок парсинга статических полей в сущностях

## Версия 1.1.0

- Предоставлено разделение страниц easyui таблиц, см MapperUtil.java

## Версия 1.0.17

- Исправление шаблонов для SQL Server (обязательно обновиться до этой версии при использовании SQL Server базы данных)

## Версия 1.0.16

- Аннотация `@Condition` добавляет атрибут `ignoreEmptyString`, https://durcframework.gitee.io/fastmybatis/#27040701

## Версия 1.0.15

- Оптимизация производительности (стандарт Alibaba + Sonar)

## Версия 1.0.14

- Оптимизация кода (Sonar)

## Версия 1.0.13

- Объединение PR2, https://gitee.com/durcframework/fastmybatis/pulls/2

## Версия 1.0.12

- Исправление шаблонов

## Версия 1.0.11

- Оптимизация свойства копирования

## Версия 1.0.10

- Улучшение Mapper.xml, разные Mapper файлы могут указывать один namespace, который будет объединён в конечном итоге

## Версия 1.0.9- Оптимизация методов преобразования объектов

## 1.0.8

- Исправление ошибки при передаче `pageSize` = 0

## 1.0.7

- Конструктор параметров может получать свойства родительского класса

## 1.0.6

- Добавлено игнорирование условий в `EasyuiDtagridParam`

## 1.0.5

- Поддержка параметров таблицы EasyUI

## 1.0.4

- Исправление ошибки отображения мапперов без сущностной модели

## 1.0.3

- Добавлена возможность принудительного выполнения запроса, см. `TUserMapperTest.testForceQuery()`

## 1.0.2

- Улучшение комментариев
- Оптимизация кода

## 1.0.1 Первый выпуск
1
https://api.gitlife.ru/oschina-mirror/durcframework-fastmybatis.git
git@api.gitlife.ru:oschina-mirror/durcframework-fastmybatis.git
oschina-mirror
durcframework-fastmybatis
durcframework-fastmybatis
master