【问题标题】:How to deal with @OneToMany relation in REST如何处理 REST 中的@OneToMany 关系
【发布时间】:2017-09-03 09:32:44
【问题描述】:

我正在设计一个小的REST 应用程序,它允许执行一些基本操作。到目前为止一切顺利,我关注@Entity,称为Client,需要与@Entity 一起持久化,称为Loan

客户:

@Entity
@Table(name = "clients")
public class Client{

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

    private String name;
    private String surname;
    private String email;
    private String phone;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "client")
    private Set<Loan> loans;

    public Client() {}

    public Client(Long id, String name, String surname, String email, String phone) {
        this.id = id;
        this.name = name;
        this.surname = surname;
        this.email = email;
        this.phone = phone;
    }

   // getters/setters

}

贷款:

@Entity
@Table(name = "loans")
public class Loan{

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

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CLIENT_ID")
    private Client client;

    @Temporal(TemporalType.DATE)
    private Date startDate = new Date();

    @Temporal(TemporalType.DATE)
    private Date originTerm;

    private Float maxPossibleAmount;

    private String notes;

    public Loan() {}

    public Loan(Long id, Client client, Date startDate, Date originTerm, Float maxPossibleAmount, String notes) {
        this.id = id;
        this.client = client;
        this.startDate = startDate;
        this.originTerm = originTerm;
        this.maxPossibleAmount = maxPossibleAmount;
        this.notes = notes;
    }

 // getters/setters
}

注册客户可以通过邮递员完美运行,但是我无法理解如何为特定客户注册贷款。在尝试这样做时,PostMan 拒绝注册新贷款并显示以下消息:

{ “时间戳”:1504429329213, “状态”:400, "error": "错误请求", “异常”:“org.springframework.http.converter.HttpMessageNotReadableException”, “消息”:“JSON 解析错误:无法构造 com.reborn.xxx.backend.models.Client 的实例:没有 int/Int-argument 构造函数/工厂方法从数值 (1) 反序列化;嵌套异常是 com。 fastxml.jackson.databind.JsonMappingException:无法构造 com.reborn.xxx.backend.models.Client 的实例:没有 int/Int-argument 构造函数/工厂方法从数字值 (1)\n 在 [来源:java .io.PushbackInputStream@121b34b; line: 3, column: 12] (通过引用链: com.reborn.xxx.backend.models.Loan[\"client\"])", “路径”:“/api/loans/add” }

LoanController:

@RestController
@RequestMapping(value = "/api/loans")
public class LoanController extends BaseController {

    @Autowired
    private LoanService loanService;

    @RequestMapping(value = "/add", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity registerLoan(@RequestBody Loan loan) {
        Loan regLoan = loanService.registerLoan(loan);
        if(regLoan == null) {
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return new ResponseEntity(HttpStatus.CREATED);
    }
}

有什么想法可以实现这个目标吗?

更新1:

客户端存储库:

@Repository
public interface ClientRepository extends JpaRepository<Client, Long>{
}

LoanRepository:

@Repository
public interface LoanRepository extends JpaRepository<Loan, Long> {
}

JSON 添加客户端(有效):

{
"id": 1,
"name": "Arthur",
"surname": "Doyle",
"phone": 777458642,
"email": "adoyle@imperial.com"
}

JSON 向特定客户提供贷款(失败):

{
    "id": 1,
    "client": "http://loacalhost:8080/api/clients/find/1",
    "startDate": 20170902,
    "originTerm": 20170902,
    "maxPossibleAmount": 5555.0000,
    "notes": null
}

【问题讨论】:

  • 错误信息似乎是说没有办法仅从它的 ID 构造一个客户端。
  • 你能展示代码你是如何持久化客户和贷款的吗??
  • 呃,我不知道如何链接到当前现有的客户实体
  • @Ashish451 抱歉,我现在不能,但我可以向您保证,这两个接口都是从 jparepositories 扩展而来的
  • 好吧,根据日志问题似乎是休眠正在尝试获取/放置 id 为 1 的客户端实体,该实体在数据库中不存在。所以相应地检查你的代码

标签: json spring hibernate spring-data-jpa spring-rest


【解决方案1】:

您的LoanClient 相关联。因此,如果您想为客户创建贷款,请使用此有效负载:

POST http://loacalhost:8080/api/loans 
{
    "originTerm": ...
    "maxPossibleAmount": ...
    "notes": ...
    "client": "http://loacalhost:8080/api/clients/1"
}

不需要自定义控制器。

附:将@JsonIgnoreProperties("loans") 添加到Loan.client 以避免stackoverflow 异常...

附言在@OneToMany 中,fetch 参数默认为FetchType.LAZY,因此您可以避免它。

【讨论】:

  • 刚刚尝试了您的解决方案,但效果不佳。我收到与帖子中相同的错误,但现在关于字符串
  • @Reborn 检查我的演示项目github.com/Cepr0/sdr-one-to-many 添加Master 使用POST http://localhost:8080/api/masters 和有效负载{ "name": "master1" }。要添加Slave,请使用POST http://localhost:8080/api/slaves 和有效负载{ "name": "slave1", "master": "http://localhost:8080/api/masters/1" }
  • 在运行 POST http://localhost:8080/api/slaves with payload { "name": "slave1", "master": "http://localhost:8080/api/masters/1" }{ "cause": null, "message": "没有找到合适的 HttpMessageConverter 将请求正文读入类型为 io.github.cepr0.onetomany.bidi.Slave 的对象请求内容类型为 text/plain;charset=UTF-8!" }
  • @Reborn content-type 必须是application/hal+json;charset=UTF-8,别忘了先创建Master...
  • @Reborn 不要尝试使用以前的名称创建新的主服务器或从服务器 - 使用唯一的(参见 name 属性的 @Column 注释)。或者只是重新启动应用程序...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-17
  • 1970-01-01
  • 1970-01-01
  • 2020-11-03
  • 2014-01-18
  • 1970-01-01
相关资源
最近更新 更多