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

OSCHINA-MIRROR/selfly-dexcoder-assistant

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

新版全新重构,更加方便易用,请移步:https://gitee.com/selfly/sonsure-dumper

Dexcoder 快速开发辅助工具包

Данный универсальный dal был разработан в процессе разработки и предназначен для использования с простым инкапсулированным универсальным dao или слоем доступа к данным.

Если вам не нравятся такие ORM-фреймворки, как Hibernate или Mybaits, и вы предпочитаете Spring JdbcTemplate или DbUtils, то можете попробовать этот инкапсулированный универсальный dal, который на данный момент является самым удобным и простым в использовании универсальным dal-слоем.

Последние обновления:

Версия 2.3.5, обновление от 08.06.2016:

  • Рефакторинг функции разбивки на страницы, поддержка синтаксического анализа SQL, пользователь может свободно выбирать;
  • Исправление проблемы с потерей порядка при использовании Criteria способом сначала queryCount, а затем queryList;
  • Исправлена проблема с откатом транзакции при возникновении ошибки в RunBinder перехватчике, когда транзакция вложена, и ошибка откатывается.

Подробные журналы обновлений.

Конфигурацию динамических источников данных см. здесь: Использование динамических источников данных в dexcoder-dal и настройка разделения чтения и записи.

Разделение таблиц данных см. здесь: Реализация разделения данных по таблицам в dexcoder-dal.

Основные компоненты dexcoder-dal

Некоторые особенности dexcoder-dal:

  1. Один dao может обрабатывать все сущности, нет необходимости создавать отдельный базовый dao для каждой сущности.
  2. Помимо сущности, различные методы поддерживают более мощный способ Criteria.
  3. Условия where в SQL поддерживают некоторые сложные условия, такие как =, !=, or, in, not in и даже выполнение функций.
  4. При запросе можно указать, какое поле использовать для сортировки, и можно указать несколько полей для комбинированной сортировки по возрастанию и убыванию.
  5. При запросах можно указать белый список и чёрный список возвращаемых полей, чтобы возвращать только определённые поля или не возвращать определённые поля.
  6. Поддержка функций при запросах select, таких как count(), max(), to_char() и даже distinct.
  7. Удобная и мощная функция разбиения на страницы без дополнительных операций, всего две-три строки кода для завершения разбиения на страницы, автоматическое определение базы данных без указания.
  8. Можно использовать {} и [] для выполнения некоторых специальных операций, код в {} будет выполняться напрямую, а код в [] будет преобразован с именем, обычно fieldName преобразуется в columnName.
  9. Поддержка выполнения пользовательских SQL.
  10. Поддержка способа выполнения пользовательского SQL, аналогичного mybatis.
  11. Поддержка разделения чтения и записи и динамических источников данных.
  12. Поддержка дружественного разделения данных на таблицы.

Имена следуют принципу соглашения вместо конфигурации, типичные соглашения включают:

  • Имя таблицы USER_INFO соответствует имени класса сущности UserInfo.
  • Имя поля USER_NAME соответствует атрибуту userName в классе сущности.
  • Первичный ключ USER_INFO имеет имя USER_INFO_ID, атрибут в классе сущности также называется userInfoId.
  • Последовательность Oracle для первичного ключа USER_INFO называется SEQ_USER_INFO.

Конечно, вы можете изменить их в расширении, но это не рекомендуется, так как это хороший стандарт.

Использовать универсальный dao в проекте очень просто, он уже доступен в центральном репозитории maven, просто добавьте зависимость в pom.xml:

<dependency>
    <groupId>com.dexcoder</groupId>
    <artifactId>dexcoder-dal-spring</artifactId>
    <version>${version}</version>
</dependency>

Затем объявите bean в файле конфигурации spring следующим образом:

<bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
    <property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!--Необходимо объявить при использовании разбиения на страницы-->
<bean id="pageControl" class="com.dexcoder.dal.spring.page.PageControl"></bean>

После этого его можно внедрить в ваш Service или другие классы для использования.

Ниже приведены примеры некоторых распространённых методов, где объект Entity — это User, и он одинаков для всех объектов Entity.

Сначала рассмотрим объект User и его унаследованный Pageable:

public class User extends Pageable {
    private Long              userId;
    private String            loginName;
    private String            password;
    private Integer           userAge;
    private String            userType;
    private String            email;
    private Date              gmtCreate;
    //......
}

Объект Pageable используется для сохранения информации о количестве элементов на странице и текущей странице для поддержки разбиения на страницы.

public class Pageable implements Serializable {
    /** Количество элементов на одной странице */
    protected int             itemsPerPage     = 20;
    /** Текущая страница */
    protected int             curPage          = 1;

    //......
}

Это обычные объекты JavaBean, ниже показано, как выполнять конкретные операции вставки, удаления, изменения и запроса, демонстрируя два метода Entity и Criteria для каждой операции.

Операция вставки

Способ Entity:

User user = new User();
user.setLoginName("selfly_a");
//......
Long userId = jdbcDao.insert(user);

Способ Criteria:

Criteria criteria = Criteria.insert(User.class).into("loginName", "selfly_b").into("password", "12345678")
    .into("email", "selflly@foxmail.com").into("userAge", 22).into("userType", "2").into("gmtCreate", new Date());
Long userId = jdbcDao.insert(criteria);

###Операция сохранения, отличие от операции вставки заключается в том, что она не обрабатывает первичный ключ, который должен быть указан вызывающей стороной.

Способ Entity:

User user = new User();
user.setUserId(-1L);
//......
jdbcDao.save(user);

Способ Criteria:

Criteria criteria = Criteria.insert(User.class).into("userId", -2L).into("loginName", "selfly-2")
    .into("password", "12345678").into("email", "selflly@foxmail.com").into("userAge", 22).into("userType", "2")
    .into("gmtCreate", new Date());
jdbcDao.save(criteria);

Операция обновления

Способ Entity:

User user = new User();
user.setUserId(57L);
user.setPassword("abcdef");
//Способ один: значения null для атрибутов будут проигнорированы
jdbcDao.update(user);

//Способ два: значения null для атрибутов будут обновлены до базы данных
jdbcDao.update(user,false);

Способ Criteria:

//В способе Criteria здесь email установлен в значение null, также будет обновлён
Criteria criteria = Criteria.update(User.class).set("password", "update222").set("email",null)
    .where("userId", new Object[] { 56L, -1L, -2L });
jdbcDao.update(criteria);

Операция получения

По первичному ключу:

User user = jdbcDao.querySingleResult(критерии);

Выполнение функции

//max()
Критерии критерии = Критерии.select(User.class).addSelectFunc("max([userId])");
Длинный userId = jdbcDao.queryForObject(критерии);

//count()
Критерии критерии = Критерии.select(User.class).addSelectFunc("count(*)");
Длинный счётчик = jdbcDao.queryForObject(критерии);

//distinct
Критерии критерии = Критерии.select(User.class).addSelectFunc("distinct [loginName]");
Список<Карта<Строка, Объект>> mapList = jdbcDao.queryForList(критерии);

По умолчанию метод addSelectFunc возвращает результаты и поля таблицы взаимоисключающими, и не сортирует их. Если необходимо вернуть вместе с другими полями таблицы и использовать сортировку, можно использовать следующий код:

Критерии критерии = Критерии.select(User.class).addSelectFunc("DATE_FORMAT(gmt_create,'%Y-%m-%d %h:%i:%s') date",false,true);
Список<Карта<Строка, Объект>> mapList = jdbcDao.queryForList(критерии);

Это выполнение функций в select, но как выполнять функции в update и where? Для этого можно использовать {} и [].

Рассмотрим следующий код:

Критерии критерии = Критерии.update(User.class).set("[userAge]", "[userAge]+1")
    .where("userId", новый объект[] { 56L });
jdbcDao.update(критерии);

Этот код выполнит SQL-запрос: UPDATE USER SET USER_AGE = USER_AGE+1 WHERE USER_ID = ?. В [] fieldName преобразуется в columnName.

Также можно использовать {}, чтобы напрямую писать columnName, потому что содержимое в {} выполняется без каких-либо операций:

Критерии критерии = Критерии.update(User.class).set("{USER_AGE}", "{USER_AGE + 1}")
    .where("userId", новый объект[] { 56L });
jdbcDao.update(критерии);

Аналогично, функции можно выполнять в where:

Критерии критерии = Критерии.select(User.class).where("[gmtCreate]", ">",
    новый объект[] { "str_to_date('2015-10-1','%Y-%m-%d')" });
Список<Пользователь> userList = jdbcDao.queryList(критерии);

Поддержка псевдонимов таблиц

Иногда даже при работе с одной таблицей необходимо использовать псевдонимы таблиц, например, в Oracle с типом xmltype. В Criteria можно установить псевдоним таблицы:

Критерии критерии = Критерии.select(Table.class).tableAlias("t").addSelectFunc("[xmlFile].getclobval() xmlFile")
        .where("tableId", новый объект[]{10000002L});
Объект obj = jdbcDao.queryForObject(критерии);

//Соответствующий SQL
select t.XML_FILE.getclobval() xmlFile from TABLE t where t.TABLE_ID = ?

Использование аннотаций

Аннотации можно использовать для указания имени таблицы, первичного ключа, имени столбца или игнорирования определённого свойства. Конкретное использование кода ясно видно из следующего примера. Единственное, на что следует обратить внимание, это то, что аннотации размещаются на методах getter, а не на свойствах:

@Table(name = "USER_A", pkField = "userId", pkColumn = "USER_ID")
public class AnnotationUser extends Pageable {

    /** Пользовательский идентификатор */
    private Длинный              userId;

    /** Базовое ключевое слово */
    частная Строка            desc;

    /** Время модификации базы данных */
    частное Дата              gmtModify;
    
    //пропущено...

    @Column(name = "`DESC`")
    public String getDesc() {
        return desc;
    }

    @Transient
    public Date getGmtModify() {
        return gmtModify;
    }
}

Выполнение пользовательского SQL

В реальных приложениях некоторые сложные запросы, такие как соединения таблиц и подзапросы, неизбежны. Учитывая сложность такого SQL и необходимые оптимизации, универсальный dao не предоставляет прямой инкапсуляции, а предоставляет интерфейс для выполнения пользовательских SQL.

Существует два способа выполнения пользовательского SQL: прямое выполнение SQL и выполнение через mybatis.

Прямое выполнение SQL

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

Чтобы выполнить пользовательский SQL, сначала необходимо внедрить sqlFactory в jdbcDao. Здесь используется SimpleSqlFactory:

<bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
    <property name="jdbcTemplate" ref="jdbcTemplate"/>
    <property name="sqlFactory" ref="sqlFactory"/>
</bean>
<bean id="sqlFactory" class="com.dexcoder.dal.SimpleSqlFactory">
</bean>

Затем можно напрямую передать SQL для выполнения:

List<Map<String, Object>> list = jdbcDao.queryRowMapListForSql("select * from USER where login_name = ?",
    new Object[] { "selfly_a99" });

Эта реализация относительно проста, и параметр Object массива не поддерживает сложные пользовательские объекты.

Выполнение через mybatis

Этот подход реализован с использованием плагинов. Сначала добавьте зависимость:

<dependency>
    <groupId>com.dexcoder</groupId>
    <artifactId>dexcoder-dal-batis</artifactId>
    <version>${version}</version>
</dependency>

После этого также внедрите sqlFactory, заменив SimpleSqlFactory на BatisSqlFactoryBean:

<bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
    <property name="jdbcTemplate" ref="jdbcTemplate"/>
    <property name="sqlFactory" ref="sqlFactory"/>
</bean>
<bean id="sqlFactory" class="com.dexcoder.dal.batis.BatisSqlFactoryBean">
    <property name="sqlLocation" value="user-sql.xml"/>
</bean> **BatisSqlFactoryBean** имеет свойство **sqlLocation**, которое указывает на пользовательский файл SQL, поскольку используется способ анализа Spring, можно использовать различные подстановочные знаки так же, как и при использовании в конфигурационном файле Spring.

User-sql.xml — это XML-файл, похожий на mapper-класс MyBatis:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//dexcoder.com//DTD Mapper 2.0//EN"
        "http://www.dexcoder.com/dtd/batis-mapper.dtd">
<mapper namespace="User">
    <sql id="columns">
        user_id,login_name,password,user_age,user_type
    </sql>

    <select id="getUser">
        select
        <include refid="columns"/>
        from user
        <where>
            <if test="params[0] != null and params[0].userType != null">
                user_type = #{params[0].userType}
            </if>
            <if test="params[1] != null">
                and login_name in
                <foreach collection="params[1]" index="index" item="item" separator="," open="(" close=")">
                    #{item}
                </foreach>
            </if>
        </where>
    </select>
</mapper>

Затем вызывается код:

User user = new User();
user.setUserType("1");
Object[] names = new Object[] { "selfly_a93", "selfly_a94", "mapList = jdbcDao.queryRowMapListForSql("User.getUser", "params", new Object[] { user, names });
for (Map<String, Object> map : mapList) {
    System.out.println(map.get("userId"));
    System.out.println(map.get("loginName"));
}

Мы вызываем метод queryForSql, передавая три параметра:

  • User.getUser — конкретный идентификатор SQL, namespace + id.
  • params — ключ доступа к параметрам в пользовательском SQL, если не передан, по умолчанию используется parameters.
  • Object[] — параметры, используемые в SQL. При доступе к конкретным параметрам можно использовать parameters[0], parameters[1], соответствующие элементам внутри, поддерживаются сложные объекты.

Здесь поддерживается сложный параметр, первый — объект User, второй — массив объектов, способ получения можно увидеть в коде выше.

Помимо передачи параметров в виде массива объектов и использования способа доступа parameters[0] для доступа к соответствующим элементам, остальное аналогично MyBatis, здесь также поддерживается динамический SQL, потому что он сам происходит от MyBatis.

Кроме того, в возвращаемом результате ключи карты преобразуются из LOGIN_NAME в camelCase loginName.

Структура проекта

  • dexcoder-commons — некоторые общие инструменты, maven-зависимости можно добавлять по мере необходимости.
  • dexcoder-dal — общий интерфейс dal, здесь нет конкретной реализации для операций с базой данных. Конкретные операции с базой данных зависят от выбранного метода реализации (в настоящее время только Spring JdbcTemplate).
  • dexcoder-dal-spring — реализация Spring JdbcTemplate для dal.
  • dexcoder-dal-batis — реализация выполнения SQL с использованием mybatis.
  • dexcoder-test — тестовый проект.

Некоторые пояснения

Способ BatisSqlFactory был проанализирован после анализа исходного кода Mybatis и включает в себя большое количество кода, заимствованного из Mybatis.

JdbcDao может быть настроен с другими параметрами при объявлении:

<bean id="jdbcDao" class="com.dexcoder.dal.spring.JdbcDaoImpl">
    <property name="jdbcTemplate" ref="jdbcTemplate"/>
    <property name="sqlFactory" ref="..."/>
    <property name="mappingHandler" ref="..."/>
    <property name="rowMapperClass" value="..."/>
    <property name="dialect" value="..."/>
</bean>

— mappingHandler — по умолчанию использует DefaultMappingHandler, то есть следует указанным соглашениям, а не конфигурации, при необходимости можно реализовать этот интерфейс. — sqlFactory — при выполнении пользовательского SQL внедряется соответствующая фабрика SQL. — rowMapperClass — по умолчанию используется spring BeanPropertyRowMapper.newInstance(clazz), при необходимости можно самостоятельно реализовать, стандартный RowMapper Spring также подойдёт. — dialect — диалект базы данных, будет автоматически определяться при пустом значении, обычно не требуется внедрять.

Многие спрашивают, нужно ли мне наследовать этот dao и реализовывать свои методы? На самом деле в этом нет необходимости, вы можете использовать spring JdbcTemplate в соответствии со стандартами, чтобы реализовать свой собственный dao без привязки. Кроме того, вы всё ещё можете использовать этот универсальный компонент разбиения на страницы.

Другие основные компоненты

Спасибо & Ссылки

Часть о разбиении на страницы основана на общем плагине разбиения на страницы Mybatis: https://github.com/pagehelper/Mybatis-PageHelper

Блог: http://www.dexcoder.com/selfly

Электронная почта автора: javaer@live.com

QQ группа общения: 32261424

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

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

Введение

Уже переработана и выпущена новая версия, пожалуйста, перейдите по ссылке: https://gitee.com/selfly/sonsure-dumper Развернуть Свернуть
Отмена

Обновления

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

Участники

все

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

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