SpringBoot中json转换的正确方式和位置

问题描述 投票:0回答:2

我正在开发一个小型 SpringBoot 项目。将订单数据存储在 postgres 数据库中。我有一个为我的前端返回 json 的 API。 我问自己到底应该在哪个地方将数据转换为实际的 json。我知道有很多种方法可以做到这一点,但我想学习专业的方法。

假设订单包含 ID、日期、客户名称、产品 ID。在此示例中,当要求输入特定名称时,我只需要前端的日期作为 order_date,产品 ID 作为 Product_id。

可能的方法:

1)在我的 CrudRepository 中使用本机 postgres 查询:

@Query(value="SELECT json_build_object('order_date', o.date, 'product_id', productid) 
       from order where name=:name", nativeQuery = true)
List<Object> getOrderByName(@Param("name") String name);

然后只需在控制器方法中调用此存储库方法即可。 关于性能,转换为 json 可能是最快的方法。 我现在面临的最大缺点是您无法对 crudrepository 方法的返回值进行任何计算,因为它是一个特殊的 postgres 对象。例如,在测试中模拟这个似乎很复杂。

2)选择crudrepository中的整个对象,然后在控制器中创建json:

Order findByName(String name);

在控制器中,我将创建一个 HashMap 并返回它,假设我的 方法有一个返回类型 ResponseEntity>.

Order order = orderRepository.findByName("John Doe");
HashMap<String, String> jsonResult = new HashMap<>();
jsonResult.put("order_date", order.getName());
jsonResult.put("product_id", order.getProductId());
return jsonResult;

这样做的好处是我可以对从数据库获取的订单对象进行计算。我不必使用丑陋的 sql 查询,并且可以利用我的 ORM 系统的优势。最大的缺点是,我总是必须在每个控制器方法的末尾创建这个自定义 json,这感觉是错误的。

3) 使用 JPA 投影。我没有尝试,但我读到了它(https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

做这个相当标准的动作的专业方法是什么?在更大的企业应用程序中是如何完成的?大型企业应用程序是否使用 jpa crudrepository 之类的东西或如何与 java 中的数据库交互?

java postgresql hibernate spring-boot jpa
2个回答
1
投票

假设您有一个“标准”项目结构:控制器、服务、存储库和域模型 - 为简洁起见,省略了

import

控制器

@Controller
@RequestMapping("/entities")
public final class TheController {
  private final TheService service;

  @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
  public ResponseEntity<Collection<JpaEntity>> getAll() {
    return ResponseEntity.ok(service.searchAll());
  }

  @GetMapping(path = "{entity-id}", produces = MediaType.APPLICATION_JSON_VALUE)
  public ResponseEntity<?> getById(final @PathVariable("entity-id") String id) {
    final Optional<JpaEntity> result = service.searchById(UUID.fromString(id));
    if (result.isPresent()) {
      return ResponseEntity.ok(result.get());
    }
    return ResponseEntity.notFound().build();
  }
}

服务

@Service
@Transactional
public class TheService {
  private TheRepository repository;

  @Transactional(readOnly = true)
  public Collection<JpaEntity> searchAll() {
    return repository.findAll();
  }

  @Transactional(readOnly = true)
  public Optional<JpaEntity> searchById(final UUID id) {
    return repository.findById(id);
  }
}

存储库

public interface TheRepository extends JpaRepository<JpaEntity, UUID> { }

领域模型

@Entity
@Table(name = "tb_name")
public final class JpaEntity extends AbstractPersistable<UUID> {
  @Column(name = "column1", length = 128, nullable = false)
  private String one;

  @Column(name = "column2", length = 128, nullable = false)
  private String two;

  // No-args constructor, getters, etc.
}

使用此结构,当响应发送到用户代理时,Spring Boot 将为

JpaEntity
生成适当的 JSON 表示形式。

提示: 如果您想更多地控制哪些字段被序列化(反序列化),您可以利用

@JsonView
注释。


0
投票

您首先需要一个可以映射到您的表的实体以及该实体的 CRUD/JPA 存储库。您可以查询存储库(在控制器中)并控制 API 发回的字段(映射到表的列)。

下面是一个示例(您需要包含 spring web 依赖项以启用自动 Jackson 配置)。这里@JsonIgnore注解,忽略JSON响应中的字段。但它将在java对象中可用。

@Entity
public class Order {

    @Column(name = "product_id")
    protected Long productId;

    @Column(name = "order_date")
    protected Date orderDate;

    @JsonIgnore
    @Column(name = "order_number")
    protected Date orderNumber;

    //setters and getters

}

@Transactional
public interface OrderRepo extends JpaRepository<Order, Long>{
}

@Controller
public class OrderController
{

  public OrderController(){}

  @Autowired
  OrderRepo orderRepo;

  @GetMapping(/orders/{id})
  public Order findOrder(@PathVariable("id")long id)
  {
   return orderRepo.findById(id);
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.