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

OSCHINA-MIRROR/osjoe-turbo

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

Здесь и далее:

  • Текст запроса переведён на русский язык.
  • Оригинальный формат текста сохранён.
  • Специальные символы или непечатаемые символы оставлены без перевода в результате.

Написать в начале

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

Я планирую в основном представить структуру ORM (объектно-реляционное отображение), которая находится внутри структуры и называется «TURBO» (турбина) (потому что это ядро системы, поэтому я хотел использовать двигатель в качестве имени). Позже я поделюсь компонентами структуры, такими как проверка разрешений, единый вход, мониторинг и передача.

В последнем коде была проведена модульная разбивка, и в то же время были представлены другие компоненты, используемые в проекте. Если вам интересно, вы можете скачать и посмотреть. Адрес: https://gitee.com/base100/turbo.git

Весь набор ORM основан на springjdbc и использует механизм отражения Java для реализации. Здесь у некоторых студентов может возникнуть вопрос: «Зачем создавать ещё один ORM, когда уже есть hibernate и MyBatis?»

Первоначальная цель

  1. Мне не нравится hibernate и MyBatis из-за большого количества конфигураций XML, поэтому я хочу избежать конфигурации, если это возможно. Эта идея также продолжается в моих собственных продуктах: простота — это красота.

  2. Поскольку я когда-то был администратором базы данных Oracle, я сам контролирую базовую сборку SQL, оставляя дверь открытой для будущей оптимизации, вместо того чтобы позволить hibernate и mybatis делать всё, сохраняя прозрачность и возможность вставлять собственные методы оптимизации на нижнем уровне.

  3. Я хочу использовать объектный запрос, писать SQL и смешивать их по своему усмотрению.

  4. Чтобы соответствовать моему интерфейсному фреймворку, сделать взаимодействие между слоями MVC более лёгким и избежать преобразования различных PO, BO, VO, DTO, POJO туда и обратно.

  5. Бесшовное переключение между несколькими источниками данных, без изменения кода. Во-первых, конфигурация должна быть максимально простой, а во-вторых, нижний уровень должен поддерживать общие синтаксисы различных баз данных.

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

  7. Возможность динамически создавать источники данных.

  8. Можно ли обойтись без слоя DAO в MVC?

  9. Удобство подключения к различным таблицам и разделам запросов и т. д.

  10. (50% первоначальной цели) Когда я был молод и безрассуден, у меня не было девушки, и я был одержим кодом, работая над ним до двух часов ночи. Я чувствовал необходимость создать что-то, что продемонстрировало бы мои навыки.

  11. Волосы важны.

Давайте теперь рассмотрим этот ORM на примере.

В настоящее время ORM поддерживает следующие базы данных: Oracle, MySQL, SQLserver, PostgreSQL, с возможностью расширения поддержки других баз данных.

Этот текст будет следовать следующему процессу:

  1. Конфигурация источника данных;
  2. Конфигурация объектных отношений;
  3. Операции вставки, удаления, изменения и запроса, транзакции, операции с несколькими источниками данных и динамическое создание источников данных.

1. Конфигурация источника данных

Можно одновременно настроить несколько источников данных, и драйвер не нужно настраивать (нижний уровень напрямую ищет различные драйверы баз данных в соответствии с URL-адресом соединения), которые являются старыми драйверами, которые не меняются десятилетиями, но каждый раз, когда они настраиваются, студенты ищут их в Baidu.

Конфигурация по умолчанию для базы данных

db.default.url=jdbc:mysql://localhost:3306/test

db.default.username=root

db.default.password=root

db.default.initPoolSize=5

db.default.maxPoolSize=5

db.default.schema=test

# Второй источник данных (может быть бесконечное количество), v2 ниже представляет псевдоним второго источника данных, который можно настроить по желанию. На самом деле он используется в операциях.

db.v2.url=jdbc:postgresql://10.237.33.127:5432/test

db.v2.username=test

db.v2.password=123456

db.v2.initPoolSize=5

db.v2.maxPoolSize=5

2. Конфигурация объектов и отношений и внедрение;

Мы внутренне называем весь поддерживаемый MVC трёхслойный объект как VO, и нет абсолютного стандарта. Мы используем аннотации (annotation), но мы постарались максимально упростить их. Позже мы представим, что MVC имеет только один слой, который может использоваться в качестве объекта переднего плана для получения значений формы и может быть непосредственно вставлен в базу данных в соответствии с конфигурацией annotation.

Приведу пример.

Сначала создайте таблицу!

Чтобы показать, что эта структура поддерживает различные типы полей, мы создали несколько типов полей с различными типами данных, таких как символьные, CLOB, BLOB и временные метки.

DROP TABLE IF EXISTS `t_user`;

CREATE TABLE `t_user` (

  `id` char(32) DEFAULT '' COMMENT 'Идентификатор пользователя',

  `name` varchar(255) DEFAULT NULL COMMENT 'Имя пользователя',

  `email` varchar(255) DEFAULT NULL COMMENT 'Электронная почта',

  `head_sculpture` blob COMMENT 'Изображение профиля',

  `resume` longtext COMMENT 'Резюме',

  `ts` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'Отметка времени'

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Посмотрите на аннотацию VO (короткая книга делает макет настолько раздражающим, что он не поддерживает вставку кода, поэтому здесь я сделал снимок экрана, get и set здесь опущены, но на самом деле они существуют).

На следующем рисунке видно, что все свойства, соответствующие именам полей базы данных, не требуют аннотаций. Они не вставляются в базу данных, но используются для приёма данных форм переднего плана. Свойства, использующие @WsdNotDbColumn, могут быть аннотированы.

@WsdTable(name="T_USER")
public class UserVo extends ModuleFeatureBean{
  
    /**
     * Идентификатор пользователя
     */
    @WsdColumn(isId=true)
    private String id;
    /**
     * Имя пользователя
     */
    private String name;
    
    /**
     * Электронная почта пользователя
     */
    private String email;
    
    /**
     * Резюме
     */
    @WsdColumn(type=TYPE.CLOB)
    private String  resume;
    /**
     * Изображение профиля
     */
    @WsdColumn(type=TYPE.BLOB,name="head_sculpture")
    private byte[] headSculpture;
    
    /**
     * Отметка времени
     */
    private Date ts;
    
    /**
     * Значение, полученное интерфейсом для использования на сервере, не вставляется в базу данных
     */
    @WsdNotDbColumn
    private String token;

Здесь давайте посмотрим на аннотации, связанные с ORM:

  1. Аннотация таблицы (wsdTable):
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WsdTable {

    /**
     * Название схемы в данных
     * @return
     */
     String schema()default "";
    /**
     * Наименование таблицы
     * @return
     */
    String name() default "";
    /**
     * Требуется ли sharding (разделение таблиц), необходимо искать конфигурацию разделов, соответствующую текущей таблице, в class-path table_sharding.xml
     * @return
     */
    boolean sharding() default false;
    
}
  1. Аннотация поля (WsdColumn — ключевая аннотация):

Здесь определены сопоставления различных типов полей базы данных для удобства адаптации одного и того же псевдонима к различным типам баз данных.

Например, NUMBER может быть сопоставлен с («number», «int», «tinyint», «decimal», «float», «double», «bigint», «numeric»), представляя псевдонимы для разных баз данных с одинаковыми типами. Вот перевод текста на русский язык:

NUMBER(Integer.class, Long.class, Double.class, int.class, double.class, long.class), TIMESTEMP(Date.class), VARCHAR2(String.class), BLOB(byte[].class), CLOB(String.class);

private TYPE() {
    this.equalClazz = new Class<?>[]{};
}

private Class<?>[] equalClazz;

private TYPE(Class<?>... equalClazz) {
    this.equalClazz = equalClazz;
}

public Class<?>[] getequalClazz() {
    return equalClazz;
}

} /**

  • 数据库字段分组

  • @author 公众号:18岁fantasy

  • @2014-11-21 @下午7:53:24 */ public static enum DB_TYPE_GROUP { NUMBER("number", "int", "tinyint", "decimal", "float", "double", "bigint", "numeric"), TIMESTAMP("timestamp", "timestamp with local time zone", "timestamp with time zone"), DATE("date", "datetime", "time"), STR("varchar2", "varchar", "char", "nvarchar2", "nvarchar"), BLOB("blob"), CLOB("clob", "ntext", "text", "longtext");

    private String[] dbType;

    DB_TYPE_GROUP(String... dbType) { this.dbType = dbType; }

    public String[] getDbType() { return dbType; }


### 3、配置启动扫描

Здесь нужно сказать, что в рамках проекта был разработан механизм запуска движка с конфигурационным файлом, который определяет местоположение объектов VO, которые должны быть просканированы. Несколько пакетов для сканирования разделяются вертикальной чертой.

Таким образом, при запуске проекта происходит сканирование этих пакетов и сохранение метаданных всех обнаруженных объектов VO в контенте или кэш-сервисе. Для более подробного ознакомления с процессом можно обратиться к исходному коду.
com.zlxd.*|core.* ```

Сканирование реализовано аналогично тому, как это сделано в spring, и реализовано в классе ModuleParser.

4、Различные операции с данными

В этом разделе рассматриваются примеры операций с данными, включая удаление, изменение, поиск и использование нескольких источников данных, а также использование вне среды spring. Все примеры доступны в классе DaoTest. ** Уже есть список часто используемых методов для работы с базой данных** Входная картинка

4.1 Вставка данных Для небольших проектов мы обычно не пишем слой DAO. Вместо этого мы используем CM для прямого доступа к сервису через сервисный слой. CM — это класс, который служит точкой входа для сервисов (конечно, сервисы также могут быть внедрены с помощью spring).

  1. Вставка объекта

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

/**
   * Тестирование вставки объекта
   */
  @Test
  public void testInsert() {
    try {
      UserVo u = new UserVo();
      u.setId(UUIDGenerator.getUUID());
      u.setName("n_n");
      u.setEmail("email@163.com");
      u.setHeadSculpture(FileUtil.readFileToByteArray(new File("d:\\hp.png")));
      u.setResume("简历内容");
      u.setTs(new Date());
      CM.getDao().insertModule("Тестирование вставки объекта", u);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  1. Пакетная вставка
  @Test
  public void testBatchInsert() throws IOException {
    try {
      List<UserVo> users = new ArrayList<UserVo>();
      for (int i = 0; i < 50; i++) {
        UserVo u = new UserVo();
        u.setId(UUIDGenerator.getUUID());
        u.setName("n_" + i);
        u.setEmail("email@" + i + ".com");
        u.setHeadSculpture(FileUtil.readFileToByteArray(new File("d:\\hp.png")));
        u.setResume("简历内容" + i);
        u.setTs(new Date());
        users.add(u);
      }
      CM.getDao().batchInsertModule("Тестирование пакетной вставки объекта", users);
    } catch (DaoException e) {
      e.printStackTrace();
    }
  }

4.2 Операции поиска

  1. Поиск по списку
@Test
  public void testListModule() {
    try {

      List<UserVo> users = CM.getDao().listModule("Тестирование поиска на основе объектов", UserVo.class, null);
      CollectionUtil.printCollection(users);
    } catch (DaoException e) {
      e.printStackTrace();
    }}
  1. Поиск по id
  @Test
  public void testGetById() {
    try {

      String[] idValuds = {"3f1d35b12ab544fdb73badc750e534e2"};
      UserVo user = CM.getDao().getModuleById("Поиск по id", UserVo.class, idValuds);
      FileUtil.writeByteArrayToFile(new File("d:\\hp2.png"), user.getHeadSculpture());
      System.out.println(user);

    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  1. Условный поиск

Все условия объединены в классе WhereCondition, который использует цепную структуру для упрощения процесса. 4.5 Транзакции В рамках одной транзакции выполняется несколько DDL-операций.

@Test
public void doInSingleTransationCircle() {
    try {

      UserVo user = new UserVo();
      user.setId("bc17b776423241479354f6a4e6a2e261");
      user.setName("new_name");

      Dao dao =  CM.getDao();

      CM.getDao().doInSingleTransationCircle("事务操作", new SingleTransationCircleWithOutResult() {
        
        @Override
        public void actionInCircle() throws RuntimeException {
          try {
            dao.insertModule("插入", user);

            user.setEmail("email@1.1");
            WhereCondition condition = new WhereCondition();
            condition.where().lessThan("Ts", "2019-05-08 15:47:11");
            dao.updateModule("修改", user, condition);

            dao.deleteModuleById("删除", user);
          } catch (DaoException e) {
            throw new RuntimeException(e);
          }
        }
      });

    } catch (DaoException e) {
      e.printStackTrace();
    }
  }

4.6 Операции с несколькими источниками данных

  1. Сначала необходимо заранее настроить информацию о нескольких источниках данных в файле конфигурации. Настройка проста и может поддерживать несколько источников данных. Например:
#默认数据库配置 
db.default.url=jdbc:mysql://localhost:3306/test
db.default.username=root
db.default.password=root
db.default.initPoolSize=5
db.default.maxPoolSize=5
db.default.schema=test

#其他数据源
db.pg.url=jdbc:postgresql://10.237.33.127:5432/test
db.pg.username=test
db.pg.password=123456
db.pg.initPoolSize=5
db.pg.maxPoolSize=5
  1. В CM определите:
public class CM extends CmCommon{


  private static final String PG_DBNAME = "pg";
  /**
   * 获另外的的数据源操作类
   */
  public static Dao getPGDao() {
    
    return getDao(PG_DBNAME);
    
  }
}
  1. Затем можно вызвать напрямую:
  @Test
  public void multDataSource() {
    try {
     
      //默认数据源
      CM.getDao().listModule("测试基于对象查询列表", UserVo.class, null);
      //另外的数据源
      CM.getPGDao().listModule("测试基于对象查询列表", UserVo.class, null);
      
    } catch (DaoException e) {
      e.printStackTrace();
    }
  }

4.7 Динамическое создание источника данных Используется в основном в ситуациях, когда через интерфейс добавляется источник данных, например, динамическое добавление базы данных для последующего мониторинга или динамическая конфигурация источника данных в ETL.

/**
 * 可在非spring环境下使用各种方法。常用场景如,比如要动态添加一个对数据库对其进行监控
 */
public static void main(String[] args) throws Exception {
    
    //数据源参数
    DataSourceProperty dataSourceProperty = new DataSourceProperty();
    dataSourceProperty.setJdbcUrl("jdbc:mysql://localhost:3306/test");
    dataSourceProperty.setUsername("root");
    dataSourceProperty.setPassword("root");
    dataSourceProperty.setInitialSize(1);
    dataSourceProperty.setMaxActive(1);
    
    Dao dmDao = DaoFactory.createDao("动态数据源数据源", dataSourceProperty);
    List<Map<String, Object>> users = dmDao.listMap("查询", "select *  from t_user where ts<?", new Object[] {"2019-5-8 15:08:43"});
    CollectionUtil.printCollection(users);
  }

Это всё, что касается введения в ORM в рамках данной структуры.

Вы можете загрузить код из указанного адреса Git и протестировать его шаг за шагом.

Ещё раз спасибо за вашу работу. Я надеюсь, что вы сможете использовать эту структуру для написания кода и создания фреймворка. Также приглашаю вас подписаться на мой публичный аккаунт, duomi88.

Также есть публичный аккаунт в WeChat, приглашаем подписаться.

Введите сюда описание изображения

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

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

Введение

Описание недоступно Развернуть Свернуть
GPL-2.0
Отмена

Обновления

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

Участники

все

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

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