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

OSCHINA-MIRROR/mirrors-FastSQL

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

И (AND)

Метод Описание
eqByType(Object) Соединение строк с помощью оператора «=», в зависимости от типа аргумента. Например, eqByType(1) генерирует 1, а eqByType("1") генерирует '1'.

ИЛИ (OR)

Метод Описание
byType(Object) Генерирует строку в соответствии с типом аргумента, например, byType(1) создаёт 1, byType("1") создаёт '1'

4.3 Использование соединения для запросов и сортировки

Запрос на оценку ниже проходного балла:

sqlFactory.sql().SELECT("s.name","c.subject_name","c.score_value")
        .FROM("score c")
        .LEFT_JOIN_ON("student s", "s.id=c.student_id")
        .WHERE("c.score_value<60")
        .ORDER_BY("c.score_value")
        .build();
/*
Генерируется SQL-запрос:
SELECT s.name, c.subject,c.score_value
FROM score c
LEFT OUTER JOIN student s ON (s.id = c.student_id)
WHERE c.score_value < 60
ORDER BY c.score_value
*/

4.4 Групповые запросы

Запрос общей оценки каждого студента:

sqlFactory.sql().SELECT("s.name", "sum(c.score_value) total_score")
        .FROM("score c")
        .LEFT_JOIN_ON("student s", "s.id=c.student_id")
        .GROUP_BY("s.name")
        .build()
/*
Генерируется SQL-запрос:

SELECT s.name, sum(c.score_value) total_score
FROM score c
LEFT OUTER JOIN student s ON (s.id = c.student_id)
GROUP BY s.name
*/

4.5 IN-оператор

Поскольку Jdbc не поддерживает привязку параметров IN, FastSQL предлагает несколько способов непосредственного объединения IN-оператора:

  1. Использование строки:
//1.Использование строки
sqlFactory.sql().SELECT("*")
   .FROM("student")
   .WHERE("name").IN("('小明','小红')")
   .build();
  1. Использование коллекции (List, Set и т. д.):
//2.Использование коллекции (List,Set и т.д.)
sqlFactory.sql().SELECT("*")
   .FROM("student")
   .WHERE("name").IN(Lists.newArrayList("小明","小红"))
   .build();
  1. Использование массива:
//3.Использование массива
sqlFactory.sql().SELECT("*")
   .FROM("student")
   .WHERE("name").IN(new Object[]{"小明","小红"})
   .build();
  1. Использование переменного параметра (наиболее лаконично):
//4.Использование переменного параметра (наиболее лаконично)
sqlFactory.sql().SELECT("*")
   .FROM("student")
   .WHERE("name").IN_var("小明","小红")
   .build();

Генерируемый SQL-запрос: SELECT * FROM student WHERE name IN ('小明', '小红').

4.6 Использование метода $_$() для подзапросов

Запрос оценок выше среднего (можно использовать метод $_$())

sqlFactory.sql().SELECT("*")
   .FROM("score")
   .$_$(
         sqlFactory.sql().SELECT("avg(score_value)").FROM("score")
    )
   .WHERE("score_value >")
   .build();
//Генерируется SQL-запрос:
//SELECT *  FROM score  WHERE score_value >  ( SELECT avg(score_value)  FROM score )

Подзапросы с использованием IN

sqlFactory.sql().SELECT("*")
    .FROM("score")
    .$_$(
         sqlFactory.sql().SELECT("DISTINCT score_value").FROM("score")
    ).WHERE()
    .AND("score")
    .IN()
    .build();
//Генерируется SQL-запрос: SELECT * FROM score WHERE 1 = 1 AND score IN (SELECT DISTINCT score_value FROM score)

Примечание: для сложных SQL-запросов рекомендуется использовать прямое построение строк:

String sql="SELECT * FROM score WHERE 1 = 1 AND score IN (SELECT DISTINCT score_value FROM score)";
sqlFactory.sql().str(sql);

4.7 Использование AND и OR вместе

В запросе нет информации об использовании AND и OR вместе. Использование beanParameter метода и добавление параметра

Map<String, Object> param = new HashMap<>();
param.put("name", "李%");

sqlFactory.sql()
    .SELECT("*")
    .FROM("student")
    .WHERE("name").LIKE(":name")
    .AND("age > :age")
    .beanParameter(param)  // Устанавливаем один параметр DTO
    .addParameterMapItem("age", 12) // Добавляем
    .queryList(StudVO.class);

Использование varParameter метода — поддержка ? заполнителя и переменных параметров

SQL sql = sqlFactory.sql();
sql.INSERT_INTO("student", "id", "name", "age")
    .VALUES("?", "?", "?")
    .varParameter("123", "小明")
    .varParameter(12)
    .update();

5.3. Методы запроса

5.3.1. Анализ методов запроса

  • T queryOne(Class<T> returnClassType) — запрос одного результата строки, упакованного в объект. Параметр может быть String/Integer/Long/Short/BigDecimal/BigInteger/Float/Double/Boolean или любым классом POJO.
  • Map<String, Object> queryMap() — запрос одной строки результата, упакованной в карту.
  • List<T> queryList(Class<T> returnClassType) — запрос нескольких строк результатов, упакованных в список объектов.
  • List<Map<String, Object>> queryMapList() — запрос нескольких строк результатов, упакованных в массив карт.
  • List<Object[]> queryArrayList() — запрос результатов, упакованных в общий список массивов.
  • ResultPage<T> queryPage(int page, int perPage, Class<T> returnClassType) — страница запроса результатов.

5.3.2. Пример

StudentVO — класс представления для запроса, содержит поля name и age. StudentDTO — класс параметров запроса, содержащий поле name.

// queryList может запрашивать список, который может быть списком базовых типов или списком объектов
List<String> strings = sqlFactory.sql().SELECT("name")
                .FROM("student")
                .queryList(String.class); // Здесь выполняется запрос списка и указывается тип возвращаемого значения

List<StudVO> studVOList = sqlFactory.sql().SELECT("name", "age")
                            .FROM("student")
                            .WHERE("name=:name")
                            .beanParameter(new StudentDTO())  // Устанавливается один параметр DTO
                            .queryList(StudVO.class);     // Запрашивается список объектов

// queryOne может запросить одно значение, которое может быть базовым типом или объектом
String name = sqlFactory.sql().SELECT("name")
                 .FROM("student")
                 .WHERE("id=:id")
                 .AND("name=:name")
                 .mapItemsParameter("id", 12345) // Можно передать несколько значений k-v, также можно вызвать parameterMap для передачи параметра Map
                 .addParameterMapItem("name", "Jack")// Использование addParameterMapItem для добавления значений k-v
                 .queryOne(String.class);  // Здесь выполняется запрос одного объекта (базовый тип) и указывается тип возвращаемого значения

StudVO studVO = sqlFactory.sql().SELECT("name", "age")
                   .FROM("student")
                   .WHERE("name=:name")
                   .beanParameter(new StudentDTO())  // Устанавливается один DTO
                   .queryOne(StudVO.class);     // Запрос одного объекта

// queryPage запрос страницы
ResultPage<StudVO> studVOResultPage =sqlFactory.sql().SELECT("name", "age")
                                        .FROM("student")
                                        .queryPage(1, 10, StudVO.class);  // Запрос страницы (первая страница, 10 записей на страницу)
// В соответствии с конкретной базой данных выполнить запрос страницы
ResultPage<StudVO> studVOResultPage =sqlFactory.sql().SELECT("name", "age")
                                        .FROM("student")
                                        .queryPage(1, 10, StudVO.class, DbType.MY_SQL);

Обратите внимание: после вызова queryOne, если запрошенное значение не существует, будет выброшено исключение EmptyResultDataAccessException, а не null, поэтому необходимо использовать тип упаковки для получения его значения вместо базового типа и проверять ненулевое значение.

Обратите внимание: queryPage возвращает объект ResultPage.

5.3.3. Различные RowMapper

Интерфейс RowMapper

RowMapper — это интерфейс в Spring-jdbc, он может упаковывать данные каждой строки в пользовательский класс.

public interface RowMapper<T> {

    /**
     * Spring будет вызывать итерацию по результатам запроса и каждый раз вызывать этот метод для преобразования результатов запроса в объекты.
     */
    T mapRow(ResultSet rs, int rowNum) throws SQLException;
}

Методы queryXXX в классе SQL поддерживают этот интерфейс, используйте следующим образом:

List<StudentVO> list 
         = sqlFactory.sql().SELECT("name", "age")
                .FROM("student")
                .queryList(new RowMapper<StudentVO>() {
                    @Override
                    public StudentVO mapRow(ResultSet rs, int rowNum) throws SQLException {
                        StudentVO studentVO = new StudentVO();
                        studentVO.setName(rs.getString("name"));
                        studentVO.setAge(rs.getInt("age"));
                        return studentVO;
                    }
                });

BeanPropertyRowMapper реализация (spring-jdbc реализация)

Автоматическое связывание, имена столбцов и имена классов Java должны совпадать, например: атрибут «userName» может соответствовать полю базы данных «USERNAME» или «user_name». Таким образом, нам не нужно вручную привязывать их. Класс SQL использует этот класс при запросе результатов как составного объекта, и в большинстве случаев нет необходимости вызывать его вручную. ColumnMapRowMapper — реализация класса (spring-jdbc реализация).

Результаты упаковываются в виде карты. Большая часть SQL-класса queryMap/queryMapList использует этот класс, и в большинстве случаев нет необходимости вызывать его вручную.

SingleColumnRowMapper — реализация класса (spring-jdbc реализация).

Большая часть SQL-класса queryList/queryOne использует этот класс при получении результатов с одной колонкой, таких как List, List, Long, Date. В большинстве случаев нет необходимости вызывать его вручную.

PartialBeanPropertyRowMapper — реализация класса (fastsql реализация).

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

CombinedBeanPropertyRowMapper — реализация класса (fastsql реализация, тестирование продолжается).

Сопоставляется со сложными результатами, используется вместе с аннотацией InnerBeanMapped.

5.4 Операции добавления, изменения и удаления данных

Для операций вставки:

// вставка
sqlFactory.sql().INSERT_INTO("student", "id", "name", "age")
        .VALUES(":id", ":name", ":age")
        .mapItemsParameter("id", 678, "name", "Kiven", "age", 123)
        .update();

Для операций изменения:

sqlFactory.sql().UPDATE("student")
        .SET("name",":name")
        .WHERE("id=678")
        .mapItemsParameter("id", 678, "name", "Rose", "age", 123)
        .update();

Для операции удаления:

sqlFactory.sql().DELETE_FROM("student")
        .WHERE("id=:id")
        .mapItemsParameter("id", 678)
        .update();

5.5 Управление транзакциями

Управление транзакциями вручную с помощью инструмента класса Spring org.springframework.jdbc.datasource.DataSourceUtils:

Connection connection = DataSourceUtils.getConnection(dataSource);// открыть транзакцию
connection.setAutoCommit(false);// отключить автоматическую фиксацию

sqlFactory.sql()
     .INSERT_INTO("sys_users", "id").VALUES(":id")
     .mapItemsParameter("id", 456)
     .update();

sqlFactory.sql()
    .INSERT_INTO("sys_users", "id").VALUES(":id")
    .mapItemsParameter("id", 234)
    .update();

//connection.rollback(); // откатить

connection.commit();// зафиксировать транзакцию

5.6 Пакетные операции

6 BaseDAO

6.1 Подготовка данных

Entity класс сущности

Используются следующие аннотации:

  1. @Table — необязательная, если не указана, будет проанализирована как student (в соответствии с формой имени класса с подчёркиванием).
  2. @Id — обязательная, соответствует первичному ключу таблицы.
  3. @Entity — необязательная, рекомендуется для совместимости со стандартом JPA.

Пример:

@Entity
@Table(name="student")
@Data  //use lombok
public class Student {
    @Id
    private Integer id;
    private String name;
    private Integer age;
    private LocalDate birthday;
    private String homeAddress;
}

Создайте новый класс DAO слоя доступа к данным, наследуя от BaseDAO, чтобы автоматически наследовать методы BaseDAO (см. часть 2).

Класс DAO в среде Spring

Класс DAO уровня:

@Repository
public class StudentDAO extends BaseDAO<Student,Integer> {

}

Если SQLFactory настроен как Spring @Bean, он будет автоматически внедрён. В сервисе вы можете использовать этот DAO:

@Service
public class StudentService {
    @Autowire
    private StudentDAO studentDAO;

    @Transactional //если требуется транзакция--org.springframework.transaction.annotation.Transactional
    public void test1(){
        studentDAO.XXX();//вызов любого метода
    }

}
Класс DAO вне среды Spring
public class StudentDAO extends BaseDAO<Student,String> {

}
public class Test  {
    public static void main(String[] args) {
        SQLFactory sqlFactory = ...

        StudentDAO studentDAO= new StudentDAO();
        studentDAO.setSqlFactory(sqlFactory);//вручную внедрить
        //выполнить операцию
        studentDAO.XXX();
    }
}

6.2 Основные методы использования CRUD

CRUD — это аббревиатура четырёх основных операций с данными: C означает создание, R — чтение, U — обновление, D — удаление. BaseDAO автоматически создаёт методы обработки данных в таблице.

Вставка данных

Метод int insert(E entity) вставляет значения объекта в базу данных, значения null будут установлены в NULL в сгенерированном SQL-запросе.

Student student = new Student();
student.setId(2);
student.setName("小丽");
student.setBirthday(LocalDate.now());//здесь используется тип времени jdk8
student.setHomeAddress("");

studentDao.insert(student);//получить сохранённый идентификатор

//эквивалентный SQL-запрос (обратите внимание, что возраст установлен в null)
//INSERT INTO student(id,name,age,birthday,home_address) VALUES (2,'小丽',NULL,'2017-07-11','')

Метод int insertSelective(E entity), вставляет в базу данных значения объекта, отличные от null.

Student student = new Student();
student.setId(3);
student.setName("小丽");
student.setBirthday(new Date());
student.setHomeAddress("");
studentDao.insertSelective(student);

//эквивалентный SQL-запрос (обратите внимание на то, что возраст не сохраняется, в слое базы данных возраст будет сохранён как значение по умолчанию для таблицы, если значение по умолчанию не установлено, оно будет сохранено как null)
//===>INSERT INTO student(id,name,birthday,home_address)  VALUES  (3,'小丽','2017-07-11','')
Изменение данных

Метод int update(E entity) , обновляет данные на основе объекта (поля null в базе данных будут установлены в null), поле @id объекта не может быть пустым.

//ожидает обновления

Метод int updateSelective(E entity) , обновляет данные на основе объекта (обновляются только поля объекта, отличные от null), поле @id объекта не может быть пустым.

//ожидает обновления

Метод int updateByColumn(E entity, String... columns) , обновляет столбцы, указанные параметрами columns, на основе идентификатора, поле @id объекта не может быть пустым.

Student student = studentDAO.selectOneById(44);
student.setAge(19);
studentDAO.updateByColumn(student,"age");

//===>UPDATE student SET age=? WHERE id=?
``` ### Данные удаление

**Метод `int deleteOneById(String id)`**  согласно идентификатору удаляет данные.
```java
int num = studentDao.deleteOneById(2);//получение количества удалённых строк
//===>DELETE FROM student WHERE id=2

Метод int deleteAll() — удаляет все строки из таблицы.

int number = studentDao.deleteAll();//получение количества удалённых строк
// ===>DELETE FROM student

Метод int[] deleteInBatch(List<String> ids) — удаляет данные в пакетном режиме согласно списку идентификаторов (все операторы удаления будут отправлены в базу данных одновременно).

List<String> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
studentDao.deleteInBatch(ids);//возвращение количества успешных удалений

Метод int deleteWhere(String sqlCondition, Object... values) — удаление согласно условию.

Запрос одной записи

**Метод E selectOneById(String id)** — поиск объекта по идентификатору.

Student student = studentDao.selectOneById(4);//поиск данных с id 12345678 и их упаковка в класс Student

Метод E selectOneWhere(String sqlCondition, Object... values), E selectOneByEntity(E entity) — поиск по условию или сущности.

Student student = studentDao.selectOneWhere("name=? AND home_address=?", "小明", "成都");

**Методы E selectOneWhere(String sqlCondition, SqlParameterSource parameterSource) и E selectByEntity(E entity)** — запрос одной записи.

Запрос нескольких записей

**Метод List<E> selectWhere(String sqlCondition, Object... values)** — возвращает одну или несколько записей, максимальное количество параметров — три.

List<Student> studentList  =  studentDao.selectWhere("name=?", "小明");
List<Student> studentList  =  studentDao.selectWhere("ORDER BY age");
List<Student> studentList  =  studentDao.selectWhere("home_address IS NULL ORDER BY age DESC");
//...

Метод List<E> selectAll() — возвращает все записи.

List<Student> allStudents  =  studentDao.selectAll();

Метод List<E> selectWhere(String sqlCondition, SqlParameterSource parameterSource), List<E> selectByEntity(E entity) — возвращает одну или несколько записей.

Пагинация

Метод ResultPage<E> selectPageWhere(String sqlCondition, int pageNumber, int perPage, Object... values), ResultPage<E> selectPage(int pageNumber, int perPage) — пагинация.

Другие запросы

Метод int countWhere(String sqlCondition, Object... values) — подсчёт записей согласно условию.

int countWhere = studentDao.countWhere("age >= 20"); //поиск студентов старше 20 лет
int countWhere = studentDao.countWhere("age > ?" , 10); //поиск студентов, возраст которых больше 10

**Метод int countWhere(String sqlCondition, SqlParameterSource parameterSource)** — подсчёт согласно условию.

@Repository
public class BizPhotoDAO extends ApplicationBaseDAO<BizPhotoPO, String> {
    public int countByName() {
        return countWhere("photo_name=:name", new MapSqlParameterSource().addValue("name", "物品照片"));
    }
}

Метод int count() — подсчет общего количества записей в таблице.

6.3 Настройка собственного ApplicationBaseDAO

Рекомендуется реализовать собственный ApplicationBaseDAO в своей программе, что позволит:

  • настроить некоторые общие методы;
  • обеспечить поддержку нескольких баз данных;
  • установить триггеры в BaseDAO.
public abstract class ApplicationBaseDAO<E, ID> extends BaseDAO<E, ID> {
  //добавление методов и т. д.
}

////Наш StudentDAO теперь должен наследовать от ApplicationBaseDAO
@Repository
public class StudentDAO extends ApplicationBaseDAO<Student,Integer> {

}

Настройка общих методов

Например, добавлен метод logicDelete для логического удаления, который будет применяться ко всем DAO, которые его наследуют.

public abstract class ApplicationBaseDAO<E, ID> extends BaseDAO<E, ID> {
  //...другие методы

  public void logicDelete(ID id) {
      //для каждой таблицы есть столбец defunct, 1 означает (логически) удалено
      namedParameterJdbcTemplate.getJdbcOperations().update("UPDATE " + this.tableName + " SET defunct = 1");
  }

  //...другие методы
}

В методе logicDelete используется переменная tableName. В классе BaseDAO доступны следующие переменные:

Class<E> entityClass; //класс сущности DAO
Class<ID> idClass;  //тип первичного ключа, помеченного @Id

Logger log; //журнал, можно использовать непосредственно в классе реализации

String className; //имя класса сущности
String tableName; //имя таблицы

Field idField;  //@Id соответствует полю ссылки
String idColumnName; //имя столбца первичного ключа

namedParameterJdbcTemplate //шаблон jdbc

//...ожидает обновления

Поддержка нескольких источников данных

public abstract class OracleApplicationBaseDAO<E, ID> extends BaseDAO<E, ID> {
      //переопределение метода setSqlFactory
      @Autowired
      @Qualifier("sqlFactory1")//===>внедрение по имени
      @Override
      protected void setSqlFactory(SQLFactory sqlFactory) {
          super.setSqlFactory(sqlFactory);
      }
}
public abstract class MySqlApplicationBaseDAO<E, ID> extends BaseDAO<E, ID> {
      //переопределение метода setSqlFactory
      @Autowired
``` ### Настройка перехватчиков в BaseDAO

```java
@Qualifier("sqlFactory2")//===>根据名称注入
      @Override
      protected void setSqlFactory(SQLFactory sqlFactory) {
          super.setSqlFactory(sqlFactory);
       }}
}

Настройка перехватчиков в классе BaseDAO

public abstract class ApplicationBaseDAO<E, ID> extends BaseDAO<E, ID> {
    public ApplicationBaseDAO() {
         // 1.Настройка триггера
         this.useBeforeInsert = true; //Перед вставкой
         this.useBeforeUpdate = true; //Перед обновлением
    }

    //2.Переписываем методы триггеров
    @Override
    protected void beforeInsert(E object) {
        EntityRefelectUtils.setFieldValue(object, "createdAt", LocalDateTime.now());
        EntityRefetectUtils.setFieldValue(object, "updatedAt", LocalDateTime.now());//При вставке данных автоматически записываются createdAt и updatedAt
    }

    @Override
    protected void beforeUpdate(E object) {
        EntityReflectUtils.setFieldValue(object, "updatedAt", LocalDateTime.now());//При обновлении данных автоматически обновляется updatedAt
    }
}

Соответствующие отношения:

count — параметр, который показывает количество успешных выполнений.

Включение Метод, требующий перезаписи Воздействие
useBeforeInsert beforeInsert (E entity) insertSelective (..)/insert (..) выполняется перед вставкой
useAfterInsert afterInsert (E entity, int count) insertSelective (..)/insert (..) выполняется после вставки
useBeforeUpdate beforeUpdate (E entity) updateSelective (..)/update (..) выполняется перед обновлением
useAfterUpdate afterUpdate (E entity, int count) updateSelective (..)/update (..)/updateByColumn (..) выполняется после обновления
useBeforeDelete beforeDelete (ID id) deleteOneById (..) выполняется до удаления
useAfterDelete void afterDelete (ID id, int count) deleteOneById (..) выполняется после удаления

6.4 Использование SQL-конструктора в BaseDAO

В BaseDAO интегрирован SQL-конструктор, в унаследованном от него классе вы можете напрямую вызвать getSQL(), чтобы получить экземпляр SQL:

@Repository
public class StudentDAO extends ApplicationBaseDAO<Student, String> {
    /**
     * Запрос списка студентов по имени
     */
    public List<Student> queryListByName() {
        return getSQL().SELECT("*").FROM(this.tableName)
                       .WHERE("name").LIKE("'李%'")
                       .queryList(Student.class);//Запрос списка
    }
    
    /**
    * Изменить имя студента на основе старого имени
    */
    public int updateName(String oldName,String newName) {
        return getSQL().UPDATE(this.tableName).SET("name = '"+newName+"'").WHERE("name").eqByType(oldName).update();
    }
}

7 Универсальные инструменты

7.1 Получение списка IN

FastSQLUtils.getInClause(Collection<?> collection) автоматически определяет, какой разделитель использовать, исходя из типа Collection:

FastSQLUtils.getInClause(Lists.newArrayList(1, 23, 4, 15));
//Генерирует=>(1,23,4,15)

FastSQLUtils.getInClause(Lists.newArrayList("dog", "people", "food", "apple")); 
//Генерирует=> ('dog','people','food','apple')

Примечание: функция IN уже интегрирована в метод IN SQL-конструктора.

7.2 Получение LIKE подстановочных знаков

FastSqlUtils.bothWildcard("李"); // => %李%
FastSqlUtils.leftWildcard("李");  // => %��ли
FastSqlUtils.rightWildcard("李"); // => ��ли%

8 Конфигурация

Чтобы отобразить журнал SQL, необходимо настроить соответствующий уровень журнала для соответствующих классов: org.springframework.jdbc.core.JdbcTemplate — настройка уровня журнала на debug покажет операторы SQL. org.springframework.jdbc.core.StatementCreatorUtils — настройка уровня журнала на trace покажет процесс привязки параметров.

Вот конфигурация Springboot:

#Отображение SQL
logging.level.org.springframework.jdbc.core.JdbcTemplate=debug
#Отображение связанных параметров
logging.level.org.springframework.jdbc.core.StatementCreatorUtils=trace

9 Прочее

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

1.3.3

Добавлены методы selectByEntity и selectOneByEntity в BaseDAO.

1.2.1

  1. Переписан код для получения общего количества строк, что решает проблему низкой эффективности разбиения на страницы при запросе.

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

FastSQL — это простой ORM-фреймворк, основанный на spring-jdbc. Он поддерживает построение SQL, выполнение SQL, связывание именованных параметров, автоматическое сопоставление результатов запроса и универсальные DAO. Развернуть Свернуть
Apache-2.0
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/mirrors-FastSQL.git
git@api.gitlife.ru:oschina-mirror/mirrors-FastSQL.git
oschina-mirror
mirrors-FastSQL
mirrors-FastSQL
master