【问题标题】:CRUD API Spring Boot Make a Copy of an entryCRUD API Spring Boot 复制条目
【发布时间】:2020-09-30 07:18:09
【问题描述】:

我正在尝试制作我从 CRUD 存储库中获取的实例的副本。我想存储一个实例的副本,但使用不同的主键。在我在服务类中制作的复制方法中,当我尝试制作副本时,它会抛出一个错误,提示 org.hibernate.HibernateException: identifier of an instance of SpringBootStarter.Topic.Topic was altered from <id> to <new_id> 当我在制作副本后向邮递员发出 GET 请求时,我希望在结果中同时查看原始和副本(但副本具有不同的主键。)

有人可以帮帮我吗?


import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Topic {

    @Id
    private String id;
    private String name;
    private String description;

    public Topic(){

    }

    public Topic(String id, String name, String description) {
        this.id = id;
        this.name = name;
        this.description = description;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

下面是控制器类


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class TopicController {

    @Autowired
    private TopicService topicService;

    @GetMapping("/topics")
    public List<Topic> getAllTopics(){
        return topicService.getAllTopics();
    }

    @GetMapping("/topics/{id}")
    public Topic getTopic(@PathVariable String id){
        return topicService.getTopic(id);
    }

    @PostMapping("/topics")
    public void addTopic(@RequestBody Topic topic){
        topicService.addTopic(topic);
    }

    @PostMapping("topics/{id}/{new_id}")
    public void copyTopic(@PathVariable String id, @PathVariable String new_id){
        topicService.copyTopic(id, new_id); }

    @PutMapping("/topics/{id}")
    public void updateTopic(@RequestBody Topic topic, @PathVariable String id){
        topicService.updateTopic(topic, id);
    }

    @DeleteMapping("/topics/{id}")
    public void deleteTopic(@PathVariable String id){
        topicService.deleteTopic(id);
    }
}

下面是服务类

package SpringBootStarter.Topic;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class TopicService {

    @Autowired
    private TopicRepository topicRepository;

    public List<Topic> getAllTopics(){
        List<Topic> topics = new ArrayList<>();
        topicRepository.findAll().forEach(topics :: add);

        return topics;
    }

    public Topic getTopic(String id){
        Optional<Topic> optional = topicRepository.findById(id);
        return optional.get();
    }

    public void addTopic(Topic topic){
        topicRepository.save(topic);
    }

    public void copyTopic(String id, String new_id){
        Topic topic = topicRepository.findById(id).get();
        Topic topicCopy = topic;
        topicCopy.setId(new_id);
        addTopic(topicCopy);
    }

    public void updateTopic(Topic topic, String id){
        topicRepository.save(topic);
    }

    public void deleteTopic(String id){
        topicRepository.deleteById(id);
    }

}

以下是主题库


import org.springframework.data.repository.CrudRepository;

public interface TopicRepository extends CrudRepository<Topic, String> {


}

【问题讨论】:

    标签: java spring-boot hibernate crud


    【解决方案1】:

    持久化上下文包含所有实体的生命周期。当您获取实体时,它将是该事务中的附加实体。因为你的对象的引用没有改变,持久化上下文会知道它仍然是数据库中的同一个对象,不允许它的标识符改变。 如果要创建新条目,则必须使用 new 关键字创建一个新对象并将其持久化。

    所以不要像这样改变标识符

    public void copyTopic(String id, String new_id){
        Topic topic = topicRepository.findById(id).get();
        Topic topicCopy = topic;
        topicCopy.setId(new_id);
        addTopic(topicCopy);
    }
    

    创建一个新的主题实体并像这样持久化它

    public void copyTopic(String id, String new_id){
        Topic topic = topicRepository.findById(id).get();
        Topic topicCopy = new Topic(topic);
        topicCopy.setId(new_id);
        addTopic(topicCopy);
    }
    

    我的建议是阅读 Hibernate 的基础知识,因为使用 ORM 时有很多陷阱。在不了解基本知识的情况下开始使用它绝不是一个好主意。

    【讨论】:

      猜你喜欢
      • 2021-09-20
      • 1970-01-01
      • 2020-04-12
      • 2021-06-10
      • 2019-04-04
      • 2018-02-08
      • 2019-04-23
      • 1970-01-01
      • 2017-09-17
      相关资源
      最近更新 更多