java - Spring + Hibernate RESTful 资源

标签 java spring hibernate rest

我是 Spring 的新手,我正在尝试创建一个 RESTful 资源以在我的 API 上使用。到目前为止,我能够列出元素 (GET/people.json)、显示特定元素 (GET/people/{id}.json)、创建新元素 (POST/people.json) 和删除元素 (删除/people/{id}.json)。我的最后一步是处理更新方法 (PUT/people/{id}.json,但我还不知道该怎么做。

这是我的 Controller 代码:

包 com.example.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.example.model.Person;
import com.example.service.PersonService;

import java.util.Map;

@Controller
public class PersonController {

    @Autowired
    private PersonService personService;

    @ResponseBody
    @RequestMapping(value = "/people.json", method = RequestMethod.GET)
    public String all(Map<String, Object> map) {
        return "{\"people\": " + personService.all() + "}";
    }

    @ResponseBody
    @RequestMapping(value = "/people/{personId}.json", method = RequestMethod.GET)
    public String show(@PathVariable("personId") Integer personId) {
        Person person = personService.find(personId);
        return "{\"person\": "+person+"}";
    }


    @ResponseBody
    @RequestMapping(value = "/people.json", method = RequestMethod.POST)
    public String create(@ModelAttribute("person") Person person, BindingResult result) {
        personService.create(person);
        return "{\"person\": "+person+"}";
    }

    @ResponseBody
    @RequestMapping(value = "/people/{personId}.json", method = RequestMethod.PUT)
    public String update(@PathVariable("personId") Integer personId, @ModelAttribute("person") Person person, BindingResult result) {
        personService.update(personId, person);
        return "{\"person\": "+person+"}";
    }    

    @ResponseBody
    @RequestMapping(value = "/people/{personId}.json", method = RequestMethod.DELETE)
    public String delete(@PathVariable("personId") Integer personId) {
        personService.delete(personId);
        return "{\"status\": \"ok\", \"message\": \"\"}";
    }
}

这是我的服务代码:

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.model.Person;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import java.util.List;

@Service
public class PersonServiceImpl implements PersonService {

    @PersistenceContext
    EntityManager em;

    @Transactional
    public List<Person> all() {
        CriteriaQuery<Person> c = em.getCriteriaBuilder().createQuery(Person.class);
        c.from(Person.class);
        return em.createQuery(c).getResultList();
    }

    @Transactional
    public Person find(Integer id) {
        Person person = em.find(Person.class, id);
        return person;
    }

    @Transactional
    public void create(Person person) {
        em.persist(person);
    }

    public void update(Integer id, Person person) {
        // TODO: How to implement this?
    }

    @Transactional
    public void delete(Integer id) {
        Person person = em.find(Person.class, id);
        if (null != person) {
            em.remove(person);
        }
    }   
}

那么,对于 Spring、hibernate 专家来说,完成我需要的最好方法是什么?同样重要的是,资源更新只更新实际改变的属性

谢谢,

最佳答案

更改您的 PersonService 更新方法签名,使其返回一个 Person,此外,您不需要单独的 id,只需使用Person 对象保存 id。他们实现了这样的方法:

public Person update(Person person) {
    // you might want to validate the person object somehow
    return em.merge(person);
}

同时相应地更新您的网络服务层。要么更改它以便 personId 不再存在,要么保留它并使用它设置 Person id:

public String update(@PathVariable("personId") Integer personId, 
        @ModelAttribute("person") Person person, BindingResult result) {
    person.setId(personId);
    Person updated = personService.update(person);
    // You may want to use a JSON library instead of overriding toString.
    return "{\"person\": " + updated + "}";
}   

一个小陷阱,合并也可能会保留新实体。因此,如果您想确保 update 仅更新现有的 id,请将其主体更改为类似以下内容:

public Person update(Person person) {
    if(em.find(Person.class, person.getId()) == null) {
        throw new IllegalArgumentException("Person " + person.getId() 
                + " does not exists");
    }
    return em.merge(person);
}

It is also important that the resource update only updates the actual changed attributes

如果你希望 hibernate 只更新你的 JSON 对象和数据库之间不同的属性,可以在 @ 上使用 dynamicUpdateselectBeforeUpdate 属性的方便组合org.hibernate.annotations.Entity(查看 Hibernate Manual )。只有在您确实需要该行为(这是非标准行为并且可能会降低性能)时才启用此功能。

@org.hibernate.annotations.Entity(dynamicUpdate = true, selectBeforeUpdate = true)

在 Hibernate 4.0 上,那些不推荐使用的属性,您可以使用单独的注释来代替:

@DynamicUpdate
@SelectBeforeUpdate

关于java - Spring + Hibernate RESTful 资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22178327/

相关文章:

java - Spring资源事务管理

hibernate - java.sql.SQLException : Invalid value for getInt() - 'foo'

java - EJB 3事务回滚问题

java - Hibernate 坚持零而不是双值

java - 在 JPA 或 Hibernate 查询中使用 Constructor Result 会影响性能吗?

java - 运行 "Android update project --path ."返回无效的参数数量

java - XLS - 条件格式 - Java POI 示例

java - 安卓报警管理器 : how to find out the time remaining to trigger the PendingIntent

spring - 哪个版本的spring支持open jdk或反之请确认

java - 无法在 Spring MVC 中发送 POST 请求