4

我有一个实现接口的 JPA 实体,我想通过 jax-rs 端点仅公开该接口定义的字段。看起来像:

public interface ConnectedAppExternal {
 
 String getId();

 String getName();

}
@Entity(name="connected_application")
public class ConnectedApp implements ConnectedAppExternal {

  @Id
  @Column(name="id")
  private id;

  @Column(name="name")
  private String name;

  @Column(name="internal_status")
  private String internalStatus;

...

 @Override
 public String getId(){
   return this.id;
 }

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

 public String getInternalStatus(){
   return this.internalStatus;
 }

 public void setId(String id){
   this.id = id;
 }

 public void setName(String name){
   this.name = name;
 }

 public void setInternalStatus(String internalStatus){
   this.internalStatus= internalStatus;
 }

 ...
  
}

@Path("/applications")
public class ConnectedAppResource {

  @Inject
  ConnectedAppService appService;

...

  @GET("applications/{id}")
  @Produces("application/json")
  public ConnectedAppExternal getConnectedApplication(@PathParam("id") String id){
    return appService.getAppById(id);
  }

...

}

即使我让我的 jax-rs 资源@GET方法返回ConnectedAppExternal响应,Moxy 也会序列化整个 JPA 实体及其所有属性,因此我最终要么必须添加@JsonbIgnore到每个我不想公开的新内部实体字段;或者定义一个只包含暴露接口字段的 DTO,这意味着大量的映射和对齐开销(更多代码 => 更多错误/意外泄漏)。

(我很确定没有,因为我已经看过序列化程序代码,但只是要求一个像这样工作的替代方案;)

...或者至少避免由于 Moxy 默认使用 getter/setter 序列化每个字段而需要显式@JsonbIgnore/@JsonbTransient排除非公开字段,而是需要显式@JsonbProperty包含要 JSON 序列化/公开的字段

4

1 回答 1

2

作为一种方法,您可以使用所需数据声明 JPA 投影查询并从您的资源返回 Map<String, Object> 类型。像这样的东西:

@NamedQueries({
    @NamedQuery(name="ConnectedApp.findByName",
                query="SELECT c.id, c.internalStatus FROM ConnectedApp c WHERE c.name = :name")
}) 

请参阅:https ://dzone.com/articles/projection-queries-a-way-to-optimize-data-traffic或https://www.objectdb.com/java/jpa/query/named

另一种方法是使用 Jsonb 仅序列化所需的属性,有点像这样:

@GET
@Path("applications/{id}")
@Produces(MediaType.APPLICATION_JSON)
public String getApp(@PathParam("id") String id) {
    JsonbConfig config = new JsonbConfig().withPropertyVisibilityStrategy(
        new PropertyVisibilityStrategy(){

                    @Override
                    public boolean isVisible(Field field) {
                        return List.of("id", "name").indexOf(field.getName()) != -1;
                    }

                    @Override
                    public boolean isVisible(Method method) {
                        return false;
                    }
                    
                });
    Jsonb jsonb = JsonbBuilder.newBuilder().withConfig(config).build();
    return jsonb.toJson(appService.getAppById(id));
}

请在此处找到示例:https ://adambien.blog/roller/abien/entry/private_fields_serialization_with_json

于 2021-10-01T08:26:08.550 回答