当前位置: 首页 > 知识库问答 >
问题:

Spring JPA REST一对多

许博
2023-03-14

我想通过向个人实体添加地址列表来扩展使用REST访问JPA数据的示例。因此,我添加了一个带有注释的列表地址:

@Entity
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String firstName;
    private String lastName;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private List<Address> addresses = new ArrayList<>();

   // get and set methods...
}

地址类是一个非常简单的类:

@Entity
public class Address {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String street;
    private String number;
    // get and set methods...
}

最后,我添加了AddressRepository界面:

public interface AddressRepository extends PagingAndSortingRepository<Address, Long> {}

然后我试着给一个人发一些地址:

curl -i -X POST -H "Content-Type:application/json" -d '{  "firstName" : "Frodo",  "lastName" : "Baggins", "addresses": [{"street": "somewhere", "number": 1},{"street": "anywhere", "number": 0}]}' http://localhost:8080/people

我得到的错误是:

Could not read document: Failed to convert from type [java.net.URI] to type [ws.model.Address] for value 'street';
nested exception is java.lang.IllegalArgumentException: Cannot resolve URI street. Is it local or remote? Only local URIs are resolvable. (through reference chain: ws.model.Person[\"addresses\"]->java.util.ArrayList[1]);
nested exception is com.fasterxml.jackson.databind.JsonMappingException: Failed to convert from type [java.net.URI] to type [ws.model.Address] for value 'street'; nested exception is java.lang.IllegalArgumentException: Cannot resolve URI street. Is it local or remote? Only local URIs are resolvable. (through reference chain: ws.model.Person[\"addresses\"]->java.util.ArrayList[1])

创建一对多和多对多关系并向其发布json对象的正确方法是什么?

共有3个答案

梅欣然
2023-03-14

你的Rest服务不应该接受一个人而不是一个地址吗?

public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {}

或者,也许你正在尝试两种不同的rest服务,我不理解。您应该只有一个rest服务,该服务接收其中包含地址条目的人员。

苏运良
2023-03-14

我设法通过不导出引用的存储库来解决这个问题。这是在接口之上添加注释。在您的示例中,它会是这样的:

@RepositoryRestResource(exported = false)
public interface AddressRepository extends CrudRepository<Address, Long> {
}

这部分解决了这个问题,因为Spring Data不会仍然为您传播外键。但是,它会保留您的个人和地址(没有引用属于的人)。然后,如果我们再次调用API来更新这些丢失的外键,您将能够让一个人通过API及其所有链接地址——正如@Francesco Pitzalis所提到的

我希望这能有所帮助。只是最后一个音符。我仍在研究这个问题,因为我认为Hibernate不能为我们传播外键是荒谬的(以及基本的和必需的)。这应该是可能的。

编辑:这确实是可能的。下面的实现能够持久化一个实体及其子实体,并将外键传播给它们,用于基于Spring Data(Rest-因为我们正在公开存储库)、Hibernate 5.0.12Final和MySQL以及存储引擎InnoDB(不在内存数据库中)的架构

@Entity
public class Producto implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nombre;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "producto_id")
    private List<Formato> listaFormatos;
    //Constructor, getters and setters
}

https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/JoinColumn.html-这是至关重要的。

@Entity
public class Formato implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private Integer cantidad;
    private String unidadMedida;
    @ManyToOne
    private Producto producto;
    //Constructor, getters and setters
}

@RepositoryRestResource
public interface ProductoRepository extends CrudRepository<Producto, Long> {
}

@RepositoryRestResource
public interface FormatoRepository extends CrudRepository<Formato, Long> {
}

spring.datasource.url=jdbc:mysql://localhost:3306/(database name)
spring.datasource.username=(username)
spring.datasource.password=(password)
spring.jpa.show-sql=true

spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

这非常重要。你需要知道Hibernate在哪里运行SQL语句才能正确设置方言。对我来说,我的表的存储引擎是InnoDB。下一个链接有帮助。我在Spring/hibernate中使用什么mysql驱动程序?

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

我唯一无法解释的是,现在,我可以导出“child”存储库,它仍然可以正常工作。有什么想法吗,伙计们?

卜盛
2023-03-14

您应该首先发布这两个地址,然后在您的个人帖子中使用它们返回的URL(例如http://localhost:8080/addresses/1和http://localhost:8080/addresses/2):

curl -i -X POST -H "Content-Type:application/json" -d '{  "firstName" : "Frodo",  "lastName" : "Baggins", "addresses": ["http://localhost:8080/addresses/1","http://localhost:8080/addresses/2"]}' http://localhost:8080/people

如果您想先保存该人,然后添加其地址,您可以这样做:

curl -i -X POST -H "Content-Type:application/json" -d '{  "firstName" : "Frodo",  "lastName" : "Baggins"}' http://localhost:8080/people
curl -i -X POST -H "Content-Type:application/json" -d '{"street": "somewhere", "number": 1}' http://localhost:8080/addresses
curl -i -X POST -H "Content-Type:application/json" -d '{"street": "anywhere", "number": 0}' http://localhost:8080/addresses
curl -i -X PATCH -H "Content-Type: text/uri-list" -d "http://localhost:8080/addresses/1
http://localhost:8080/addresses/2" http://localhost:8080/people/1/addresses
 类似资料:
  • 我的应用程序在域级值对象之间使用了大量OneToMore和OneToOne引用,其中大多数是实体,要么是超类,要么是某物的子类。我想为我的应用程序提供一种一致(但简单)的方法来保存这些实例,实际的方法保存()就是这样 当前的问题是如何正确地实例化这些对象,以及在cassadeType中选择哪种策略,我想在保存带有其他实体引用的对象时保存嵌套对象,它现在可以工作,但只是第一次,之后我得到了一个,因为

  • 本文向大家介绍一对一、一对多的关联查询 ?相关面试题,主要包含被问及一对一、一对多的关联查询 ?时的应答技巧和注意事项,需要的朋友参考一下

  • 问题内容: 在我的elasticsearch服务器中,我只有一个索引。 (博客)索引包含多种类型。 如:,。 在标签类型中,我创建了1000多个标签,并在帖子类型中创建了10个帖子。 例如:帖子 例如:标签 我想将现有标签分配给博客帖子(即,关系=>映射)。 如何将标签分配给帖子映射? 问题答案: 您可以在Elasticsearch中使用4种方法来管理关系。在Elasticsearch博客文章-E

  • 一对多 多对一 关联模型 一对多: 一个部门有很多员工,但一个员工只能从属于一个部门 多对一: 多个员工只能属于一个部门 department 部门表,employee 员工表 egg-sequelize 实现一对多 分类表: 商品表: 分类 1------n 商品 1、model 里面建2张模型,分别是 category.js goods.js 2、catrgory.js 模型代码: modul

  • 问题内容: 好的,所以这可能是一个琐碎的问题,但是我在可视化和理解差异以及何时使用它们方面遇到困难。对于诸如单向和双向映射之类的概念如何影响一对多/多对多关系,我也还不清楚。我现在正在使用Hibernate,因此任何与ORM相关的解释都将有所帮助。 举例来说,我有以下设置: 那么在这种情况下,我将进行哪种映射?对于这个特定示例的答案肯定会受到赞赏,但我也确实希望获得何时使用一对多和多对多以及何时使

  • null 但是在Eclipse中测试它之后,它渴望得到所有的东西。 是否取决于我使用的是JPA还是Hibernate?

  • 这是项目迁移 这是时间表 这样用户就可以迁移了 这是我的项目模型 这是我的时间表模型: 这是我的用户模型 现在,我从项目返回我的查询 这是可以的,但user_id用户在timesheets.user_id我不能得到它的时间表,并得到它 此控制器按时间表中的项目id返回项目和时间表,但时间表中的用户id我不知道如何将其输入系统

  • 问题内容: hibernate映射中的默认访存类型是什么? 探索之后我知道的是: 渴望 一对一。 对于一对多来说,这是 懒惰的 。 但是在Eclipse中对其进行测试后,它对所有人都非常渴望。 是否取决于我使用的是JPA还是Hibernate? 问题答案: 这取决于您使用的是JPA还是Hibernate。 根据JPA 2.0规范,默认值为: hibernate的时候,一切都是懒惰的 更新: 最新版