Symfony2 и FOSRestBundle: получение UUID, упакованного в поле BINARY(16) из MySQL

Я столкнулся со странной проблемой, связанной с UUID.

Я разработал REST API, используя Symfony2+FOSRestBundle+JMSSerializer. Поскольку мне нужно обновить некоторые таблицы из двух источников, я подумал об использовании UUID в качестве первичного ключа для одного объекта.

Я выполнил доктрину: сопоставление: импорт для создания сущностей в моем проекте Symfony. Все правильно. В итоге я получил следующий объект (только для простоты открывая ключевое поле и сгенерированный геттер):

<?php 
namespace Stardigita\TgaAPIBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * TgaBookings
 *
 * @ORM\Table(name="tga_bookings", indexes={[...]})
 * @ORM\Entity
 */
class TgaBookings
{
    /**
     * @var string
     *
     * @ORM\Column(name="book_cd_booking_UUID", type="blob", length=16, nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
    */
    private $bookCdBookingUuid;

    /**
     * Get bookCdBookingUuid
     *
     * @return string 
    */
    public function getBookCdBookingUuid()
    {
        return $this->bookCdBookingUuid;
    }
...

Сеттер не был сгенерирован. Я все еще могу сделать это сам, и я это сделаю, так как мне нужно будет знать ключ заранее.

Данные для этого поля корректно хранятся в таблице как BINARY(16). Когда я восстанавливаю данные, вызывая метод REST GET, я получаю следующее:

[
{
    "book_cd_booking_uuid": "Resource id #1244",
    "book_cd_booking": 8,
    ....

Мой вопрос: как я могу получить фактические данные с поля?

Я предполагаю, что что-то нужно сделать в поле геттера, но я пробовал некоторые решения без какого-либо успеха.

Спасибо.

ОБНОВЛЕНИЕ: мне удалось зарегистрировать фактические данные, изменив метод getBookCdBookingUuid следующим образом:

    /**
     * Get bookCdBookingUuid
     *
     * @return string 
    */
    public function getBookCdBookingUuid()
    {
        return bin2hex($this->bookCdBookingUuid);
    }

и изменил тип на "guid" в аннотации свойства:

/**
 * @var string
 *
 * @ORM\Column(name="book_cd_booking_UUID", type="guid", length=16, nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
private $bookCdBookingUuid;

Я правильно представил шестнадцатеричный UUID в журнале, прежде чем возвращать результаты в контроллер:

[2014-11-03 19:52:07] app.ERROR: 1046684e5f6711e4a09f00089bce936a [] []

Но все еще получаю исключение, связанное с недопустимыми символами UTF:

request.CRITICAL: Uncaught PHP Exception RuntimeException: "Your data could not be encoded because it contains invalid UTF8 characters." at /var/www/tga_api/vendor/jms/serializer/src/JMS/Serializer/JsonSerializationVisitor.php line 36 {"exception":"[object] (RuntimeException: Your data could not be encoded because it contains invalid UTF8 characters. at /var/www/tga_api/vendor/jms/serializer/src/JMS/Serializer/JsonSerializationVisitor.php:36)"} []

Также не получил ответа от сервиса. Возвращается ошибка 500.

Пожалуйста, мне нужно решить эту проблему. Любые идеи приветствуются.

Спасибо.


person José Luis Gallego    schedule 30.10.2014    source источник
comment
Было бы проще использовать целое число в качестве идентификатора и добавить столбец для UUID?   -  person A.L    schedule 30.10.2014
comment
Я некоторое время рассматривал это решение, но эта таблица частично копируется на разные мобильные устройства. Они могут вставлять записи в автономном режиме и синхронизировать их, когда находятся в сети. Я думал о назначении различных авточисловых порогов, но отказался от этого, так как использование UUID проще. По крайней мере, так я думал сначала... На самом деле другое поле, которое вы видите в выходных данных, — это бывший первичный ключ.   -  person José Luis Gallego    schedule 30.10.2014
comment
Пожалуйста, мне нужна помощь с этим. Не могу решить критическую функциональную область. Мне нужно использовать двоичный UUID в первичном ключе и правильно прочитать значение.   -  person José Luis Gallego    schedule 03.11.2014


Ответы (1)


Сгенерированное значение

Я заметил, что вы используете аннотацию @ORM\GeneratedValue(strategy="IDENTITY") для свойства UUID. IDENTITY означает, что база данных должна/будет использовать автоинкременты, чего не следует делать при использовании UUID. Измените его на @ORM\GeneratedValue(strategy="NONE") или полностью удалите.

Преобразование

Строковая форма UUID (например, 01234567-89ab-cdef-0123-456789abcdef) должна быть преобразована в двоичную, когда она сохраняется в базе данных, и преобразована обратно при извлечении из базы данных.

Самый простой способ сделать это — ввести пользовательский тип. Пример см. здесь. .

Ошибки

Doctrine (даже master/2.5) имеет некоторые проблемы с использованием UUID в ассоциациях. Я пытаюсь исправить эти проблемы в PR #1178.

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

person Jasper N. Brouwer    schedule 10.11.2014