2016-06-21 2 views
0

У меня есть 2 сущностей (я удалил ненужные поля):Spring JPA сохранить уже существующий Субъект @OneToMany отношений

@Entity 
public class ApkPermissions { 
    @Id 
    @GeneratedValue 
    @JsonIgnore 
    private Long id; 

    @OneToMany 
    @Cascade({CascadeType.SAVE_UPDATE}) 
    private Collection<Permission> declaredPermissions; 
} 

и

@Entity 
public class Permission { 
    @Id 
    @GeneratedValue 
    @JsonIgnore 
    private Long id; 

    @Column(unique = true) 
    private String permissionName; 
} 

когда я сохраняю объект ApkPermissions впервые через CrudRepository у меня нет проблем, но когда я сохраняю другие ApkPermissions с некоторым разрешением, которое уже существует в таблице Permission, возникает исключение, указывающее на нарушение уникального ключа разрешенияName.

Я нашел это решение:

http://www.mkyong.com/hibernate/cascade-jpa-hibernate-annotation-common-mistake/

, что, кажется, подходит мой случай (и моя текущая реализация), но она не работает.

я получаю следующее сообщение об ошибке:

could not execute statement; SQL [n/a]; constraint [UK_l3pmqryh8vgle52647itattb9]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement", 

С MySQL:

UNIQUE KEY `UK_l3pmqryh8vgle52647itattb9` (`permission_name`) 

Временное решение retrive все соответствующее разрешение на поиск по permissionName из Repository. Тогда сохранение работает нормально. Это логично правильно, но я надеюсь, что существует более простая процедура ...

+0

Не могли бы вы включить вывод сообщения об исключении? –

+0

Я сделал это. Обратите внимание, что теперь я изменил отношения, поскольку @Pardeep предложил –

ответ

0

В сопоставлении OneToMany таблица разрешений будет иметь один дополнительный столбец, который будет внешним ключом, указывающим на ваши ApkPermissions. Для примера:

ApkPermission   Permission 
APK_ID | Name   Permission_ID | Name | APK_ID(FK) 
1  | APK1   1   | P1 | 1 
         2   | P2 | 1 

Таким образом, вы не можете указать же разрешение любой другой ApkPermission записи. Предположим, если вы хотите ввести 2 | APK2 в ApkPermission и хотите снова направить P1 и P2. Вы не можете сделать это с отношением один к другому, если только вы не введете записи P1 и P2 в таблицу разрешений. Это создаст дубликаты. Таким образом, у вас есть два варианта: либо вы удаляете уникальные ограничения (по имени разрешения), либо изменяете отображение на ManyToMany.

+0

. Вы правы, правильная связь - ManyToMany ... , но проблема сохраняется, когда я сохраняю ApkPermission, у которого есть разрешение в объявленных пакетах, которые уже существуют в db. –

+0

Вы пробовали с manyToMany? В этом случае вам понадобится еще одна таблица соединений. и новые записи войдут в новую таблицу соединений. Существует множество примеров. С OneToMany вам нужно вставить новые записи. В противном случае это не имеет никакого смысла. –

+0

Если вы все еще хотите продолжить работу с OneToMany (и это не будет нормализовано), вы можете удалить уникальное ограничение из allowName, поскольку у вас будут дубликаты. Я предлагаю попробовать с ManyToMany. Одна вещь, которую я хотел бы упомянуть, что сохранение спящего режима всегда делает запрос вставки, если первичный ключ равен нулю. В этом случае используйте saveOrUpdate. Но если ваша запись находится в БД, тогда идентификатор не должен быть нулевым, если вы пытаетесь его сохранить, иначе он всегда будет считать его новой записью. –

Смежные вопросы