对JPA实体关系管理双向关联的一些思考-该文件没有与之关联的程序

现象

在使用JPA进行实体关系管理的时候,会产生无限循环的情况,如果使用fastjson来进行序列化,则表现形式如下:

对JPA实体关系管理双向关联的一些思考


重点是address.person值:{"$ref":....}

如果你用的不是fastjson(它默认会检查该对象是否已经存在在json文本中)而是其他一些json类库,比如jackson,则会抛出`java.lang.StackOverflowError`异常(无限循环产生的栈溢出所导致).

但是,哪怕你用的是fastjson,你也无法用js来解析`{"$ref":".."}`.

解决思路

  • 使用fastjson其自带的`JSON.toJSONString(page,SerializerFeature.DisableCircularReferenceDetect)`

  • 优点:解决快速

  • 缺点:

  • 对老代码改动较大.

  • 实现较复杂,要对整体业务逻辑有清晰的认识.

  • 重新设计实体关系尽量避免双向关联,使用RESTful进行接口的暴露.(举个例子来说)

  • 优点:逻辑清晰,结构更合理

  • 缺点: 对老代码改动较大.实现较复杂,要对整体业务逻辑有清晰的认识

实体类Person

对JPA实体关系管理双向关联的一些思考

实体类Address

对JPA实体关系管理双向关联的一些思考

两个实体类之间的关系为Many Person To Many Address,只在Person实体类中进行关系的配置,避免双向关联.

下面举例说明使用RESTful来对资源进行访问的情况.

对于Person:

  • 1 查询所有Person: `/persons`

  • 2 查询某一个Person: `/persons/{person_id}`

  • 3 查询某一个Person的所有Address: `/persons/{person_id}/addresses`

  • 4查询某一个Person的某一个Address: `/persons/{person_id}/addresses/{address_id}`

如果要查询一个Address有几个Person: `/persons?address.id=xxx` (带分页,自己设置pageSize)

对于Address:

  • 1 查询所有Address: `/addresses`

  • 2 查询某一个Address: `/addresses/{address_id}`

以上是Person和Address的一些简单接口.其中**粗体**部分为关联查询.

设计的思路就是要尽量避免双向关联,然后把Person作为一个资源,把Address作为Person的一个子资源或者属性.

上述Person中的1 2 将Address作为了属性,查询时可以通过参数传递进去.而上述Person中的3 4 两个接口则将Address作为一个子资源进行管理.

如果要用Address来作为一个资源反查Person怎么办?

在一个Address管理页面,需求要求列出某一个住址下的Person:

  • 点击某一项:

Address发起`/persons?address.id=xxx`请求,取得`List<Person>`.

  • 默认显示:

在controller层对`/persons?address.id_in=xxx1,xxx2,xxx3`接口的返回值进行处理,取得`List<Address>`和其对应的`List<Person>`

总结

尽量避免双向关联,使用更合理的API设计方式,合理区分子资源和属性.

大大减少数据库压力!

支持请点赞,不喜勿喷.

每天一点点,成长多一点.

推荐阅读