2015-02-25 6 views
2

Я хочу знать, как удалить ассоциацию «многие-ко-многим» через вызов REST. Я могу создавать записи и ассоциировать их, но не понимаю, как их удалить.Удаление ассоциации через REST в Spring Data REST + HATEOAS

У меня есть проект Spring Boot, в котором я использую REST и HATEOAS, передавая службы и контроллеры и выставляю свой репозиторий напрямую.

У меня есть инструкция Модель/класс домена

@Entity 
@Table(name = "usr") 
public class User implements Serializable { 

private static final long serialVersionUID = 1L; 

@Version 
private long version = 0; 

@Id 
@GeneratedValue(generator="optimized-sequence") 
private Long id; 

@Column(nullable = false, unique = true, length = 500) 
@Size(max = 500) 
private String userName; 

@Column(nullable = false, length = 500) 
@Size(max = 500) 
private String firstName; 

@Column(nullable = false, length = 500) 
@Size(max = 500) 
private String lastName; 

@ManyToMany( fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
@JoinTable(name="user_role", 
      joinColumns={ @JoinColumn( name = "user_id", 
             nullable = false 
            ) 
         }, 
      inverseJoinColumns={ @JoinColumn( name="role_id", 
               nullable=false 
              ) 
           } 
) 
private Set<Role> roles = new HashSet<Role>(0); 

...Getters/Setters Below... 

Как вы можете видеть, у меня есть ролей элемент, который многие-ко-многим ассоциации с классом ролей, из которых код является таким :

@Entity 
public class Role { 

@Id 
@GeneratedValue(generator="optimized-sequence") 
private Long id; 

@Column(nullable = false) 
private String name; 

@Column(nullable = false) 
private String description; 

...Getters/Setters Below... 

Мои репозиториев выглядеть так:

UserRepository

public interface UserRepository extends 
     JpaRepository<User, Long>, JpaSpecificationExecutor<User> { 

    List<User> findByUserName(String username); 

} 

RoleRepository

public interface RoleRepository 
     extends JpaRepository<Role, Long> { 

} 

Теперь все хорошо. Когда я получаю доступ к корню проекта из браузера, я получаю каталог/каталог репозитория в формате JSON + HAL. Замечательно.

(Обратите внимание, что я удалить Http: // часть из приведенного ниже теста, потому что StackOverflow рассчитывает его к моей ссылке квоты)

I, используя WizTools клиент REST, HTTP.POST к роли (локальный: 8080/resttest/role) и создать новую роль. Успех, № роли №4.

Затем я отправляю POST в репозиторий пользователей для создания пользователя (localhost: 8080/resttest/users). Успех, Пользователь ID # 7 создан.

Затем я кладу в хранилище пользователя, чтобы создать ассоциацию с ролью:

PUT localhost:8080/resttest/users/7/roles 
Content-type: uri-list 
Body: localhost:8080/resttest/roles/4 

Отлично! Ассоциация сделала. Пользователь 9 теперь связан с ролью 4.

Теперь я не могу на всю жизнь выяснить, как УДАЛИТЬ эту ассоциацию.

Я отправляю HTTP DELETE вместо PUT с той же командой, что и выше.

DELETE localhost:8080/resttest/users/7/roles 
Content-type: uri-list 
Body: localhost:8080/resttest/roles/4 

Я получаю обратно: HTTP/1.1 405 Method Not Allowed

{ 
    "timestamp":1424827169981, 
    "status":405, 
    "error":"Method Not Allowed", 
    "exception": "org.springframework.web.HttpRequestMethodNotSupportedException", 
    "message":"Request method 'POST' not supported" 
} 

ответ

0

Из документов:

УДАЛИТЬ

...

405 Method Not Allowed - если объединение не является необязательным

PUT означает, что вы замените весь комплект roles. Поэтому, чтобы удалить одну ссылку, вы оставите PUT все остальные ссылки. Если у вас есть только один канал и хотите удалить его, вы бы PUT пустая коллекция:

PUT localhost:8080/resttest/users/7/roles 
Content-type: uri-list 
Body: 

BTW: Вы не отправить тело с DELETE запроса. Это не имеет смысла.

EDIT

Смотрите также this answer от разработчика Spring HATEOAS.

+0

Благодарим вас за ответ. Это многое объясняет. У меня есть два последующих вопроса. В ситуациях, когда ассоциация может быть многочисленной, есть ли способ просто УДАЛИТЬ один вместо PUT целый набор без того, который больше не нужен? Мой другой вопрос: что такое необязательная ассоциация? – BKaun

+0

Я не могу отредактировать комментарий больше. Просто хочу уточнить. Не указывая DELETE, как в нем, это должен быть метод DELETE http, это может быть любой метод, если он облегчает удаление только одной ассоциации, а не всего набора без необходимости. Или мне нужно создать репозиторий для этой таблицы мостов? – BKaun

+0

@BKaun Вы можете использовать 'POST', чтобы добавить один URI, но нет удобного способа удалить один URI. Необязательный означает, что должно быть значение. Обычно это тот случай, когда столбец не является «нулевым». Я думаю, что коллекция семантически всегда не является необязательной: она может быть пустой, но она всегда существует. – zeroflagL

6

Хотя создание запроса PUT с остальными элементами делает трюк, DELETE является принятой командой для удаления ресурса ассоциации и в большинстве случаев проще в использовании.

Что касается вашего примера, это должно работать:

DELETE localhost:8080/resttest/users/7/roles/4 

На отдельной ноте, при создании ассоциации, то ожидается, что идентификаторы URI в полезной нагрузке. Вам не нужно писать весь URL-адрес в теле, этого должно быть достаточно:

PUT localhost:8080/resttest/users/7/roles 
Content-type: uri-list 
Body: /roles/4 

Надеюсь, это поможет.

+0

Удалось работать для меня. – Taimur

+2

Это неудобно, поскольку все остальные запросы (put, post, get) зависят от ссылок, а не от ID. Чтобы выполнить код удаления, необходимо записать, чтобы извлечь идентификатор из объекта _link. –