Ограничение гибернации ConstraintViolationException. Есть ли простой способ игнорировать повторяющиеся записи? - PullRequest
17 голосов
/ 24 мая 2010

По сути, у меня есть схема ниже, и я вставляю записи, если они не существуют.Однако, когда дело доходит до вставки дубликата, он выдает ошибку, как я и ожидал.Мой вопрос заключается в том, существует ли простой способ заставить Hibernate просто игнорировать вставки, которые фактически вставляют дубликаты?

CREATE TABLE IF NOT EXISTS `method` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;


SEVERE: Duplicate entry 'GET' for key 'name'
Exception in thread "pool-11-thread-4" org.hibernate.exception.ConstraintViolationException: could not insert:

Ответы [ 7 ]

13 голосов
/ 24 мая 2010

Мой вопрос заключается в том, существует ли простой способ заставить Hibernate просто игнорировать вставки, которые фактически вставляют дубликаты?

Как Hibernate мог знать, что запись имеет неуникальное значение без фактической вставки записи?

Если вы выполняете пакетную вставку и не хотите откатывать всю транзакцию и отбрасывать сеанс в случае ConstraintViolationException (это то, что вы должны делать в теории после исключения, см. этот поток и этот предыдущий ответ ), я бы предложил использовать StatelessSession API и поймать ConstraintViolationException.

10 голосов
/ 25 мая 2010

Hibernate не может этого сделать.Однако вы можете сделать это самостоятельно.По сути, есть два варианта:

  1. Проверка на наличие дубликатов перед вставкой;или
  2. Перехватите ConstraintViolationException, а затем убедитесь, что нарушение вызвано дублированием (поскольку могут быть и другие причины, например, нулевые поля).

У первого есть недостаток:вы проверяете наличие дубликатов на каждой вставке, когда вероятность наличия дубликата может быть низкой.Последнее будет быстрее для обычного случая, когда дубликатов не возникает, но имеет недостаток, заключающийся в том, что вам нужно проверять дубликаты после лица.Когда создается ConstraintViolationException, он делает недействительным текущий сеанс;это означает, что вам нужно будет выполнить очистку перед выполнением поиска дубликата.

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

1 голос
/ 05 июля 2017

Вы можете использовать аннотацию @SqlInsert для вашей сущности, чтобы изменить использование SQL Hibernate для вставки в базу данных, в данный момент Hibernate должен использовать этот оператор

insert into method(name, id) values (?,?)

Если вы используете mysql, вы можете использовать оператор @SqlInsert, чтобы изменить вставку sql с помощью оператора insert ignore mysql

@SQLInsert(sql = "insert ignore into method(name, id) values (?,?)")

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

1 голос
/ 04 января 2016

Вы можете попробовать поймать исключение org.hibernate.exception.ConstraintViolationException и проглотить исключение в своем коде

Например:

try {
    sessionFactory.getCurrentSession().saveOrUpdate(entity);
} catch (ConstraintViolationException e) {
    // Ignore the exception here by doing nothing
}
1 голос
/ 26 мая 2010

Вместо использования createQuery () в hibernate, используйте createSQLQuery () и попробуйте запрос типа «REPLACE INTO method (id) VALUES (123);»

1 голос
/ 24 мая 2010

Точно так же, как сказал Паскаль, Hibernate не будет знать, является ли он дубликатом, до тех пор, пока он фактически не будет добавлен.

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

0 голосов
/ 05 марта 2017

, даже если вы поймаете исключение, могут возникнуть другие проблемы

try{
       session.save(O);
       session.getTransaction().commit();
    }catch (HibernateException e) {
       System.out.println("you are carched ¤#%SD¤") ;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...