【问题标题】:Hibernate add an entity with foreign key using RESTHibernate 使用 REST 添加具有外键的实体
【发布时间】:2019-04-13 16:54:50
【问题描述】:

首先,我还没有编写任何 SQL 语句来创建表。我尝试只使用 Hibernate/jpa 而不编写 SQL。

我的关系如下:一个用户可以有多个任务,一个任务只有一个用户。

我这样创建模型:

用户表:

@Entity
@Table(name="T_USER")
@EntityListeners(AuditingEntityListener.class)
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "uid")
    private Long uid;
...
}

任务表:

@Entity
@Table(name = "T_TASK")
@EntityListeners(AuditingEntityListener.class)
public class TASK{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long tid;

    @ManyToOne
    @JoinColumn(name ="oid")
    private User owner;

    public User getOwner() {
        return owner;
    }

    public void setOwner(User owner) {
        this.owner = owner;
    }
...
}

关系是任务的ownerid(oid)是用户的uid。

为了将用户保存到我的数据库中,我使用带有以下参数的邮递员:

{
    "username": "firstuser",
    "email": "firstuser@email.com"
}

为了将任务保存到我的数据库中,我使用了这个:

{
    "description": "some description",
    "oid": "12" // I also can state username of the user rather than ID
}

但是,当我执行保存任务时,任务的 oid 为 NULL。在数据访问对象中,我有:

@PostMapping("/save")
public QR createTask(@Valid @RequestBody Task task)
{
    return taskDAO.save(task);
}

1-我做错了什么?我只想向数据库添加一个具有所有者 ID 的任务,但是它返回 null 作为所有者 ID。

2-我应该先用 SQL 创建一个表吗

 Create table task(
     tid BIGINT,
     description VARCHAR(255),
     oid BIGINT,
     PRIMARY KEY(tid), FOREIGN KEY(oid) REFERENCES (user.uid))

3-我应该在TaskDAO中更改我的保存方法吗?

 public Task save(Task task)
 {
    return taskRepository.save(task);
 }

4- 我应该更改我的控制器方法(使用 RESTcall 的 createTask 方法)

5- 假设上述所有问题都已解决。如何获取用户拥有的所有任务?

6- 删除用户时如何删除任务(SQL中的大小写,但Hibernate中有任何方法)

我希望我能解释我的问题。任何反馈将不胜感激。

【问题讨论】:

    标签: java hibernate rest postman dao


    【解决方案1】:
    The hibernate builds table and foreign keys automatically.Complex queries we can write in repo/controller in hibernate syntax.
    With Crud repository we can delete , create update and read data easily.
    
        for example we have student to course one to many relation.
    
    @OneToMany
    @JoinColumn(name = "studentId", referencedColumnName = "studentId", insertable = false, updatable = false)
    private List<StudentCourses> studentCourses;
    
    in StudentController I will write
    
        @CrossOrigin(origins = "http://localhost:8090")
        @RequestMapping(value = "/registerStudentCourse",  method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = 
                MediaType.APPLICATION_JSON_VALUE )
        public StudentCourses registerStudentCourse(@RequestBody StudentCourses studentCourse) {
            if (studentCourse != null) {
                studentCourse.setLastupdated(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date()));
                studentCourse = studentCourseRepository.save(studentCourse);
            }
            return studentCourse;
        }
    
        @CrossOrigin(origins = "http://localhost:8090")
        @RequestMapping(value = "/findStudentCourses",  method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = 
                MediaType.APPLICATION_JSON_VALUE )
        public List<StudentCourses> findStudentCourses(@RequestBody String studentId) {
            List<StudentCourses> courses = new ArrayList<>();
            JSONObject requestedJSONObject;
            try {
                requestedJSONObject = new JSONObject(studentId);
                String student = requestedJSONObject.getString("studentId");
                courses = 
     studentCourseRepository.findCoursesByStudent(Long.parseLong(student));
            } catch (JSONException e) {
                // TODO Auto-generated catch block
            }
            return courses;
        }
    

    【讨论】:

      【解决方案2】:

      oid 为空,因为Task 中没有这样的字段。我认为您在这里混合了两个概念。第一个是代表 REST 数据结构的数据传输对象。这个应该有一个 oid 字段。第二个是持久实体。你有这个,它是Task 类。

      我将实现一个 TaskDTO,使用 Hibernate 的会话通过其 id 加载 User,然后从 UserTaskDTO 的其他字段构建一个 Task,然后像你一样保存任务。

      关于您的其他问题

      2 - 使用createupdate 值作为hibernate.hbm2ddl.auto,Hibernate 可以在您启动应用程序时生成或更新表。

      5 - 你可以有这个界面

      @GetMapping("/user/{id}")
      public List<TaskDTO> getTasks(@PathVariable Long id)
      

      那么我认为您无法逃避对某种条件查询的编码。

      6 - 这是通过配置与cascade = CascadeType.ALL 的关系来完成的

      【讨论】:

      • 我不想在 url 字段中使用 @GetMapping 和 id。我实现了一个虚拟任务传输对象,它与任务对象几乎相同,但它具有“oid”而不是用户对象。要在 postmapping 中使用“posttask”对象,如果我理解清楚,我必须将其转换为实体。我发现我可以使用 convertToEntity 方法,但 IntelliJ 找不到它。可能我必须先在 pom.xml 中添加依赖,然后再导入
      • 您当然可以这样做,但我建议您不要这样做。在 REST 传统中,当您检索数据而不更改系统中的任何内容时,应该使用 GET。 POST 相反是非幂等的变化。虽然在小规模原型上看起来很聪明,但在大规模应用程序中,您肯定希望您的概念(对象)与某种感知的现实保持一致。至于convertToEntity,你是指本文中的代码吗(baeldung.com/…)?
      • 嗯。我虽然 GET 用于获取信息而不更改后端服务器上的任何内容,但 POST 用于在数据库中创建实体(因此使用正文),PUT 用于更新和删除自我解释。正如您所说,我正在参考该网站的 convertToEntity 方法。但是,我不确定它是否适合我的应用程序。我使用 Spring 的全部原因不是创建实例。但它创建了一个 ModelMapper,我找不到那个的 Autowired 实体
      • 在将 HTTP 动词转换为 CRUD 操作时,我也会这样做。用于创建的 POST 肯定是非幂等更改(尽管并非所有非幂等更改都是创建):-)。我不是自动映射器的忠实拥护者,因为它们倾向于将简单的问题(忘记映射属性)转移到复杂的问题(为什么这个自动的东西不符合我的要求)。我认为这取决于您所在/与之合作的团队。首先使用 Spring 的原因应该是依赖注入,然后是与技术和协议的良好接口。
      • 我对 Spring 和其他设施知之甚少 :) 我正在尝试学习新技术并使用它们来增加我的知识。现在,我已经放弃了 ModelMapper 映射器。我创建了一个 taskDTO,并尝试使用 taskDTO 类的 getter 和 setter 获取信息,然后找到具有该信息的用户。尽管如此,该代码仍无法编译,因为它找不到 taskDTO。我在与任务相同的文件夹中创建了 taskDTO,并在类的开头使用了 @Entity 注释。还将它导入到 Controller 类中。我还应该做什么?
      【解决方案3】:

      1-我做错了什么?我只想将具有所有者 ID 的任务添加到数据库,但是它返回 null 作为所有者 ID

      首先,我会确保所有者被持久保存在数据库中,只是为了确保您有一个要引用的值

      2-我应该先用 SQL 创建一个表吗

      由于您使用的是 ORM,因此编写 SQL 查询会破坏其目的,您可以,但这并不是所有必要的,因为已经指定了关系

      3-我应该在TaskDAO中更改我的保存方法吗?

      4- 我应该更改我的控制器方法(使用 RESTcall 的 createTask 方法)

      我认为最好更改您的 createTask 方法,您可以将用户的 id 作为路径变量或查询参数包含在内,在该方法中您可以使用他们的 id 找到用户并在任务中设置用户字段,然后再将其传递给dto 保存值。 oid 为空的原因是因为你没有这样的字段。

      5- 假设上述所有问题都已解决。如何获取用户拥有的所有任务?

      在你的任务仓库中,你可以创建一个类似的方法

      Collection<Task> findAllTasksByOwnerId(Long id);
      

      6- 删除用户时如何删除任务(SQL 中的大小写,Hibernate 中是否有任何方法)

      您可以指定您已指定任务与用户之间关系的级联类型

      You can check this link for a simple tutorial on how to cascade in spring

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-13
        • 2017-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多