Статьи

Использование автоинкрементного столбца MySQL PK в атрибуте ADF Entity PK

Всем привет. Продолжая серию обходных приемов ADF + MySQL, сегодня мы увидим, что нам нужно сделать, чтобы использовать автоинкрементные колонки MySQL PK с нашими атрибутами PK ADF Entities. Если бы мы использовали базу данных Oracle, мы бы использовали oracle.jbo.domain.DBSequence вместе с последовательностью и триггером, чтобы сделать это «из коробки».

Для простоты мы собираемся изменить Java-файл, связанный с Entity, но в качестве хорошей практики у вас должна быть собственная реализация класса oracle.jbo.server.EntityImpl и настраивать JDeveloper, чтобы он использовал вашу собственную реализацию для каждого нового Сущность в вашем приложении. Проверьте этот пост для получения дополнительной информации об этом .

Это не пошаговое руководство по созданию ADF BC из таблиц, мы предполагаем, что у вас уже есть определения бизнес-компонентов.

Что вам нужно

Это таблица базы данных, которую мы собираемся использовать в этом посте:

1
2
3
4
CREATE  TABLE `test`.`Actor` (
  `id_actor` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(100) NOT NULL ,
  PRIMARY KEY (`id_actor`) );

После того как вы создали свои сущности из таблиц, JDeveloper сопоставит ваши атрибуты сущностей со столбцами таблицы и установит некоторые свойства в зависимости от типа столбца. Например, для нашего столбца PK (id_actor) JDeveloper установит атрибут как обязательное Integer и всегда обновляемый. Нам нужно изменить это, потому что мы хотим, чтобы наш PK обновлялся, пока он новый (при создании нового экземпляра), а не был обязательным (потому что мы читаем значение автоинкремента после публикации в базе данных):

ADFMySQL_EntityAtt_1

У вас может быть несколько таблиц в вашей базе данных и, следовательно, несколько сущностей в вашем приложении ADF, но не во всех таблицах могут быть автоинкрементные столбцы PK, поэтому нам нужен способ пометить или определить, когда атрибут PK сущности поступает из столбца автоинкремента в базе данных. Мы собираемся сделать это, используя набор свойств, который позволяет нам определить коллекцию свойств ключ / значение, а затем мы можем связать эти свойства с атрибутом и получить к ним доступ во время выполнения:

  1. В JDeveloper выберите: Файл–> Новый–> Из галереи…
  2. В бизнес-компонентах ADF выберите « Набор свойств». PropertySet_1
  3. Установите имя и пакет нового набора свойств:
    PropertySet_2
  4. После создания мы можем определить набор свойств ключ / значение, и если свойства будут показаны пользователям, мы даже можем определить их в переводимом режиме. Это не наш случай, поэтому мы собираемся определить непереводимое свойство:
    PropertySet_3
  5. Установите имя свойства как AI (для AutoIncrement) и его значение как true (поскольку атрибуты, которые используют этот набор свойств, поступают из столбца автоинкремента):
    PropertySet_4
  6. Теперь, когда у нас есть готовый набор свойств, мы можем использовать его в нашем атрибуте Entity PK:
    PropertySet_5

Чтобы получить значение автоинкремента для нашего атрибута PK, нам нужно переопределить реализацию по умолчанию нашего класса Entity (помните, что мы делаем это для простоты, но вы можете сделать лучше, как описано в начале этого поста). Мы можем сделать это, реализовав Java-класс для нашего Entity, а затем переопределив метод EntityImpl.doDML (int, TransactionEvent) , в котором изменения публикуются в базе данных:

  1. Перейдите в раздел Java сущности и нажмите на значок карандаша:

    Java_1

  2. Во всплывающем окне выберите « Создать объектный класс»: … и нажмите «ОК»:
    Java_2
  3. Раздел Java класса Entity теперь показывает файл Java, щелкните ссылку на имя файла Java:
    Java_3
  4. JDeveloper откроет новое окно с кодом Java. Скопируйте и вставьте следующие методы:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    ...
        @Override
        protected void doDML(int i, TransactionEvent transactionEvent) {
            //got to call first to super, so the record is posted
            //and we can then ask for the last insert id
            super.doDML(i, transactionEvent);
     
            //after the record is inserted, we can ask for the last insert id
            if (i == DML_INSERT) {
                populateAutoincrementAtt();
            }
        }
     
        /*
        * Determines if the Entity PK is marked as an autoincrement col
        * and executes a MySQL function to retrieve the last insert id
        */
        private void populateAutoincrementAtt() {
            EntityDefImpl entdef = this.getEntityDef();
            AttributeDef pk = null;
            //look for primary key with Autoincrement property set
            for (AttributeDef att : entdef.getAttributeDefs()) {
                if (att.isPrimaryKey() && (att.getProperty("AI") != null
                    && new Boolean(att.getProperty("AI").toString()))) {
                    pk = att;
                    break;
                }
            }
            if (pk != null) {
                try (PreparedStatement stmt =
                     this.getDBTransaction()
                         .createPreparedStatement("SELECT last_insert_id()", 1)) {
                    stmt.execute();
                    try (ResultSet rs = stmt.getResultSet()) {
                        if (rs.next()) {
                            setAttribute(pk.getName(), rs.getInt(1));
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    ...

    Приведенный выше код публикует изменения в базе данных, а затем спрашивает, вставляли ли мы значения. Если это так, нам нужно извлечь значение автоинкремента и установить его в нашем атрибуте PK. Обратитесь к функции MySQL LAST_INSERT_ID () для получения дополнительной информации о получении значений автоинкремента.

Хорошо, давайте попробуем наше решение. Сначала запустите модуль приложения:

RunAppModule_1

Как только появится инструмент Oracle ADF Model Tester , выберите (двойной щелчок) объект ActorView1 View Object на левой панели и щелкните зеленый значок плюса на правой панели, чтобы добавить нового Actor:

RunAppModule_2

Введите имя актера и нажмите кнопку «Сохранить изменения в базе данных» (маленькая база данных со значком контрольного списка на панели инструментов):

RunAppModule_4

Вы заметите, что значение автоинкремента теперь установлено на
атрибут idActor !

Не нужно беспокоиться о одновременных вставках, в документации MySQL говорится, что все в порядке (проверьте эту документацию ):

Использование столбцов LAST_INSERT_ID () и AUTO_INCREMENT одновременно от нескольких клиентов вполне допустимо. Каждый клиент получит последний вставленный идентификатор для последнего оператора, выполненного клиентом.

Увидимся!