首页 > 解决方案 > 如何在 Spring Boot MVC 中更新数据

问题描述

我有 Spring Boot MVC 上最常见的项目。我正在尝试通过 PUT 写入更新数据。

@RestController
@RequestMapping(CommentController.PATH)
public class CommentController {

    public final static String PATH = "/comments";

    @Autowired
    private CommentService service;

    @PutMapping("/{id}")
    public Comment update(@RequestBody Comment comment, @PathVariable Long id) {
        return service.update(id, comment);
    }
}

@Service
public class CommentService {

    @Autowired
    private CommentRepository repository;

    public Comment update(Long id, Comment entity) {
        Optional<Comment> optionalEntityFromDB = repository.findById(id);
        return optionalEntityFromDB
                .map(e -> saveAndReturnSavedEntity(entity, e))
                .orElseThrow(getNotFoundExceptionSupplier("Cannot update - not exist entity by id: " + id, OBJECT_NOT_FOUND));
    }

    private Comment saveAndReturnSavedEntity(Comment entity, Comment entityFromDB) {
        entity.setId(entityFromDB.getId());
        return repository.save(entity);
    }

}

@Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
}

@Entity
public class Comment  {
    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;

    @Column(name = "name")
    protected String name;
}

然后我编写了一个能够检查更新数据的测试:

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
// DBUnit config:
@DatabaseSetup("/comment.xml")
@TestExecutionListeners({
        TransactionalTestExecutionListener.class,
        DependencyInjectionTestExecutionListener.class,
        DbUnitTestExecutionListener.class
})
public class CommentControllerTest {

    private MockMvc mockMvc;
    private static String route = PATH + "/{id}";

    @Autowired
    private CommentController commentController;

    @Autowired
    private CommentRepository commentRepository;

    @PersistenceContext
    private EntityManager entityManager;

    @Before
    public void setup() {
        mockMvc = MockMvcBuilders.standaloneSetup(commentController)
                .build();
    }

    @Test
    public void update_ShouldReturnCreated2() throws Exception {
        int id = 1;
        String name = "JohnNew";
        Comment expectedComment = new Comment();
        expectedComment.setName(name);

        ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
        String json = ow.writeValueAsString(expectedComment);

        this.mockMvc.perform(put(route, id)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(json))
                .andDo(print());

        entityManager.clear();
        entityManager.flush();

        Comment commentUpdated = commentRepository.findById(1L).get();
        assertThat(commentUpdated.getName(), equalTo(name));        // not equals!
    }
}    

评论.xml:

<dataset>
    <Comment id="1" name="John" />
</dataset>

但问题是数据没有更新。如果启用 Hibernat 的日志记录,那么也没有对数据库的更新请求。我究竟做错了什么?

标签: javarestspring-bootspring-mvcspring-boot-test

解决方案


@Transactional缺少CommentService. 虽然在每个方法级别添加它可能会更好,但尝试将它添加到类级别以验证这可以解决问题:

@Service
@Transactional
public class CommentService {

推荐阅读