Лучший способ предотвратить нарушения уникальных ограничений с помощью JPA - PullRequest
5 голосов
/ 25 февраля 2011

У меня есть Keyword и KeywordType в качестве сущностей.Есть много ключевых слов нескольких типов.

При попытке сохранить второе ключевое слово типа ограничение уникальности нарушается, и транзакция откатывается.

В поиске я нашел несколько вариантов (некоторые из них в разных контекстах, поэтому я не уверен в их обоснованности здесь) - этот пост и этот пост советоватьпоймать исключение, которое было бы бесполезно для меня, когда я в конечном итоге, где я начал, и все еще нужно как-то сохранить ключевое слово.
То же самое относится к блокировке, предложенной для другой ситуации здесь
Пользовательские операторы вставки, предложенные в этой и этой сообщениях, не будут работать должным образом. Iдумаю, поскольку я использую Oracle, а не MySQL, а woulnd хотел бы связать реализацию с Hibernate.

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

Итак, что быбыть лучшим - самым надежным, переносимым (для разных баз данных и поставщиков сохраняемости) и вменяемым подходом здесь?

Спасибо.

Участвующие лица:

public class Keyword {

    @Id
    @GeneratedValue
    private long id;

    @Column(name = "VALUE")
    private String value;

    @ManyToOne
    @JoinColumn(name = "TYPE_ID")
    private KeywordType type;
    ...
}

и

@Entity
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = { "TYPE" }) })
public class KeywordType {

    @Id
    @GeneratedValue
    private long id;

    @Column(name = "TYPE")
    private String type;
    ...
}

Ответы [ 3 ]

4 голосов
/ 25 февраля 2011

Ваше последнее решение правильное, ИМО. Найдите тип ключевого слова и, если он не найден, создайте его.

Поймать исключение не очень хороший вариант, потому что

  • Трудно понять, какое исключение можно перехватить и сделать ваш код переносимым на JPA и DB *
  • Механизм JPA будет находиться в неопределенном состоянии после такого исключения, и в этом случае вы должны всегда выполнять откат.

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

2 голосов
/ 15 декабря 2012

Если вы используете EJB 3.1 и не возражаете против сериализации этой операции, проблема может решить одноэлементный компонент, использующий параллелизм, управляемый контейнером.

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class KeywordTypeManager
{
    @Lock(LockType.WRITE)
    public void upsert(KeywordType keywordType)
    {
        // Only one thread can execute this at a time.
        // Your implementation here:
        // ...
    }

    @Inject
    private KeywordTypeDao keywordTypeDao;
}
0 голосов
/ 25 февраля 2011

Я бы выбрал эту опцию:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...