Hibernate выберите после вставки

0

У меня возникла проблема с вставкой новых строк в мою базу данных MySQL. Я использую Spring Boot с Spring Boot Data JPA.

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

  1. Я создал таблицу sequences которая использует поле автоматического увеличения (используется как мой идентификатор для моих таблиц).
  2. Создал функцию, sequences_nextvalue() которая вставляет в таблицу sequences и возвращает новый автоматически увеличиваемый id.
  3. Затем я создал триггеры для каждой таблицы, которые запускаются перед вставкой, и заменяет поле id результатом вызова sequences_nextvalue().

Так что это прекрасно работает при вставке новых строк. Я получаю уникальные идентификаторы во всех таблицах. Проблема, с которой я столкнулась, связана с моими судами JPA.

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractBaseClass {
  @Id
  private Integer id = -1;
  ...
}

@Entity
public class ConcreteClass1 extends AbstractBaseClass {
  ...
}


@Entity
public class ConcreteClass2 extends AbstractBaseClass {
  ...
}

Я хочу иметь возможность запрашивать из абстрактного базового класса, поэтому я поместил столбец @Id в этот класс и использовал @Entity с InheritanceType.TABLE_PER_CLASS. Я также инициализировал идентификатор -1, так как идентификатор требуется вызвать save() из моего репозитория Spring Crud.

После вызова функции save() моих данных Spring CrudRepository значение -1 для id должным образом заменяется триггером MySQL, но результирующий объект, возвращаемый функцией save(), не возвращается с новым идентификатором, но вместо этого сохраняет -1, После просмотра журналов SQL оператор select не вызывается после вставки, чтобы получить новый идентификатор, но вместо этого возвращается исходный объект.

Можно ли заставить Hibnerate повторно выбрать объект после вставки, чтобы получить новый идентификатор, когда вы не используете @GeneratedValue?

Любая помощь приветствуется.

Теги:
spring
hibernate
spring-data

1 ответ

0
Лучший ответ

Просто хочу предоставить обновление по этому вопросу. Вот мое решение.

Вместо того, чтобы создавать MySQL TRIGGER для замены id на INSERT, я создал Hibernate IdentifierGenerator который выполняет CallableStatement для получения и возврата нового идентификатора.

Теперь мой абстрактный базовый класс выглядит следующим образом.

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractBaseClass {

  @Id
  @GenericGenerator(name="MyIdGenerator", strategy="com.sample.model.CustomIdGenerator" )
    @GeneratedValue(generator="MyIdGenerator" )
  private Integer id;
  ...

}

и мой генератор выглядит так.

public class CustomIdGenerator implements IdentifierGenerator {

    private Logger log = LoggerFactory.getLogger(CustomIdGenerator.class);
    private static final String QUERY = "{? = call sequence_nextvalue()}";

    @Override
    public Serializable generate(SessionImplementor session, Object object) throws HibernateException {

        Integer id = null;
        try {
            Connection connection = session.connection();
            CallableStatement statement = connection.prepareCall(QUERY);
            statement.registerOutParameter(1, java.sql.Types.INTEGER);
            statement.execute();
            id = statement.getInt(1);
        } catch(SQLException e) {
            log.error("Error getting id", e);
            throw new HibernateException(e);
        }
        return id;
    }

}

И только для справки

Таблица sequences.

CREATE TABLE sequences (
  id INT AUTO_INCREMENT PRIMARY KEY,
  thread_id INT NOT NULL,
  created DATETIME DEFAULT CURRENT_TIMESTAMP
) ^;

Функция sequence_nextvalue

CREATE FUNCTION sequence_nextvalue()
RETURNS INTEGER
NOT DETERMINISTIC
MODIFIES SQL DATA
BEGIN
  DECLARE nextvalue INTEGER;
  INSERT INTO sequences (thread_id) VALUE (CONNECTION_ID());
  SELECT id FROM sequence_values ORDER BY created DESC LIMIT 1 INTO nextvalue;
  RETURN nextvalue;
END ^;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню