简体   繁体   English

Spring Boot Rest接口如何正确划分业务层和数据层

[英]How to properly divide business and data layer in a Spring Boot Rest Interface

I am working with Spring Boot for quite some time now but have surprinsingly not encountered this type of problem before.我现在使用 Spring Boot 已经有一段时间了,但出乎意料地以前没有遇到过这种类型的问题。

Given the following Code example:给出以下代码示例:

Parent家长

@Entity
@Table(name="Parent")
@Cacheable(true)
@OptimisticLocking(type= OptimisticLockType.VERSION)
@DynamicUpdate

public class Parent implements Serializable {

   private Long id;
   private Child child;

   @Id
   public Long getId() {
     return this.id;
   }

   @ManyToOne(fetch = FetchType.EAGER)
   @JoinColumn(name = "child")
   public Child getChild(){
     return this.child;
   }
}

Child孩子

@Entity
@Table(name="Child")
@Cacheable(true)
@OptimisticLocking(type= OptimisticLockType.VERSION)
@DynamicUpdate

public class Child implements Serializable {

   private Long id;
   private String name;

   @Id
   public Long getId() {
     return this.id;
   }

   public String getName() {
     return this.name;
   }

Repository存储库

@Repository
public interface ParentRepository extends JpaRepository<Parent, Long> {}

Controller控制器

@RestController
public class RestController {

@Autowired
private ParentRepository parentRepository;


@RequestMapping(value="/data/parent/{parentid}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Optional<Parent> getParent(@PathVariable("parentid") Long parentId){
   return parentRepository.findById(parentId);
}

@RequestMapping(value = "/data/parent", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public Parent addParent(@RequestBody Parent parent) {
   return parentRepository.save(parent);   
}

The above code works fine and as expected when executing the GET method.上面的代码在执行 GET 方法时可以正常工作并且符合预期。 A result would look something like:结果将类似于:

{
  "id":1,
  "child": {
    "id":1,
    "name":"Jesus"
}
}

However, The way I need to use the POST method is to pass only the foreign key of the children that I want to connect to my parent.但是,我需要使用 POST 方法的方式是只传递我想连接到我父母的孩子的外键。 I do not want to create a whole Child Object, serialize it into JSON and add it to the request body.我不想创建整个子对象,将其序列化为 JSON 并将其添加到请求正文中。 Meaning I want to be able to POST a Parent object with a JSON like this:这意味着我希望能够使用这样的 JSON 发布 Parent 对象:

{
  "id":1,
  "child":1
}

and let the Rest Interface to the job of fetching my Child object.并让 Rest 接口完成获取我的 Child 对象的工作。

I was able to find a way to achieve this by adding another variable我能够通过添加另一个变量找到一种方法来实现这一目标

@Transient
Long childId;

to my Parent object and then in the controller, GET the corresponding Child object first and add it to the Parent before persisting.到我的父对象,然后在控制器中,先获取相应的子对象,然后在持久化之前将其添加到父对象。

However, I am quite certain that this is not a good way to solve this problem and that the solution will include dividing my data model into two seperate layers.但是,我很确定这不是解决这个问题的好方法,解决方案将包括将我的数据模型分成两个单独的层。 Unfortunately, I have not yet been able to find out how to do this exactly.不幸的是,我还不能确切地知道如何做到这一点。

I am thankful for any advise.我很感激任何建议。

You should divide your business model by layers : DTO (used for data exchanging with your REST clients) and Entities (for database operations).您应该按层划分您的业务模型: DTO (用于与 REST 客户端交换数据)和Entities (用于数据库操作)。

With that seperation you have more flexibility and can POST what you want without messing your entities with stuff like @JsonIgnore or @Transient .与分离-你有更多的灵活性和可POST你想要的东西没有用一样的东西搞乱你的实体@JsonIgnore@Transient

You will have something like:你会有类似的东西:

@PostMapping(value = "/data/parent")
public ParentDTO addParent(@RequestBody LightParentDTO parentDTO) {
   return service.save(parentDTO);   
}

and

class LightParentDTO {
  long parentId;
  long childId;
}

Note that I introduce a service.save(...) , there you can do all your DTO to Entity conversion operations.请注意,我引入了service.save(...) ,在那里您可以执行所有DTOEntity转换操作。

If I got you right, what you need to do is use the @jsonignore annotation Try this:如果我猜对了,你需要做的是使用 @jsonignore 注释试试这个:

@Entity
@Table(name="Parent")
@Cacheable(true)
@OptimisticLocking(type= OptimisticLockType.VERSION)
@DynamicUpdate

public class Parent implements Serializable {

   private Long id;
   @JsonIgnore     <========================================================
   private Child child;

   @Id
   public Long getId() {
     return this.id;
   }

   @ManyToOne(fetch = FetchType.EAGER)
   @JoinColumn(name = "child")
   public Child getChild(){
     return this.child;
   }
}

let me know if it works让我知道它是否有效

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM