Spring Data Rest Поместите не обновление с неизменяемой сущностью на SpringBoot 2.1.x - PullRequest
0 голосов
/ 20 мая 2019

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

Запросы на работу запускаются на весеннем загрузчике 2.0.3, но не на 2.1.4 &2.1.5.Однако использование метода Patch работает нормально.

Поскольку я работаю в Kotlin, мой код написан на Kotlin, но я также могу воспроизвести его с помощью Java-сущности:

Учитывая данные:

@Entity
data class MyEntityKt(
     @Id
     @GeneratedValue
     val id: UUID? = null,
     @Version
     val version: Long = 0,
     val name: String = "",
     val description: String = ""
)
@Value
@Wither
@Entity
@RequiredArgsConstructor
public class MyEntityJava {

    public MyEntityJava() {
        id = null;
        version = 0;
        name = "";
        description = "";
    }

    @Id
    @GeneratedValue
    private final UUID id;
    @Version
    private final long version;
    private final String name;
    private final String description;
}

И два соответствующих RestRepositories:

@RepositoryRestResource(path = "kotlin")
interface MyEntityRepository : JpaRepository<MyEntityKt, UUID>

@RepositoryRestResource(path = "java")
interface ImmutableEntityRepository : JpaRepository<MyEntityJava, UUID>

И в моем тесте (@SpringBootTest) я пробую следующее:

@Test
fun testPut() {
    val myEntity = myEntityRepository.save(MyEntityKt(name = "TestName", description = "TestDescription"))
    val update = this.mockMvc.perform(
        put("/kotlin/${myEntity.id}")
            .accept(MediaType.APPLICATION_JSON_UTF8)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .content(
                """
                {
                    "name": "TestNameModified",
                    "description": "TestDescriptionModified"
                }
            """.trimIndent()
            )
    )
    .andReturn().response.contentAsByteArray.let { objectMapper.readValue(it, MyEntityKt::class.java) }

    val updatedEntity = myEntityRepository.findById(myEntity.id!!).get()

    assertThat(updatedEntity.name).isEqualTo("TestNameModified")    
    assertThat(updatedEntity.description).isEqualTo("TestDescriptionModified")
}

Также ответЯ получаю:

{
    "name" : "TestName",
    "description" : "TestDescription",
    "_links" : {
    "self" : {
        "href" : "http://localhost/kotlin/fd83f256-3515-41b0-b9c7-7bfe53a367f8"
    },
    "myEntityKt" : {
        "href" : "http://localhost/kotlin/fd83f256-3515-41b0-b9c7-7bfe53a367f8"
    }
}

Я провел некоторое исследование и org.springframework.data.rest.webmvc.json.DomainObjectReader.MergingPropertyHandler#doWithPersistentProperty, который, я думаю, будет отвечать за создание обновленной версии моей сущности для сохранения, похоже, что это только установка значений на метод доступа, нона самом деле не создается обновленный объект.

В версии 2.0.3 с весенней загрузкой тестовый пример проходит, на 2.1.5, однако сущность не обновляется, и фактическая причина не указана (например, вывод журнала), почемусущность не обновляется.Я предполагаю, что это как-то связано с тем, что объекты неизменны, но я не понимаю, почему это работало ранее.

РЕДАКТИРОВАТЬ: я загрузил тестовый пример в Github

1 Ответ

0 голосов
/ 21 мая 2019

Я нашел решение моей проблемы:

  1. Аннотировать сущность как неизменную
  2. Сделать версию и свойство id изменяемым
@Entity
@org.springframework.data.annotation.Immutable
data class MyEntityKt(
     @Id
     @GeneratedValue
     var id: UUID? = null,
     @Version
     var version: Long = 0,
     val name: String = "",
     val description: String = ""
)

Неизменяемая аннотация вызвала ответ json, который я получал правильно обновленным, но он вставил новую запись в базу данных с моими обновленными значениями.

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

Также в json, который я отправляю для обновления сущности, я включил версию, чтобы работать для последующих обновленийкак это:

{
    "name": "TestNameModified",
    "description": "TestDescriptionModified",
    "version": 0
}
...