JAX-RS /实体最佳实践

时间:2014-09-01 15:17:45

标签: java-ee jpa jaxb jax-rs

在我的项目中,我使用JAX-RS将一些实体暴露给javascript前端框架(AngularJS)。

我不想急于加载我的实体关系,我宁愿有多种方法来获取客户需要的任何关系。

要将我的实体序列化为JSON / XML,我使用JAXB并将关系的id添加到类中。我现在最终将我的实体作为一个实体以及一个DTO。

在每个POST上,我需要设置我的实体的引用。

我想知道它是否是暴露实体的合适方式,还是有更好的方法?

一个例子总是比长文本更清晰,这里是:

@XmlRootElement
@Entity
public class Country {
    @Id
    @GeneratedValue
    private Integer id;

    private String countryName;

    @ManyToOne
    private Region region;

    @Transient
    private Integer regionId;

    // getters & setters

    // AVOID SERIALIZING REGION
    @XmlTransient
    public Region getRegion ...

    // SERIALIZE REGION ID INSTEAD
    public Integer getRegionId() {
        if (region != null)
            return region.getId();
        else
            return null;
    }

    ...

}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class Region {
    @Id
    @GeneratedValue
    private Integer id;

    private String regionName;

    // getters & setters

    ...

}

@Stateless
@Path("countries")
public class CountryResource {

    @PersistenceContext
    private EntityManager em;

    @GET
    public List<Country> getAll() {
        return em.createNamedQuery("Country.findAll", Country.class).getResultList();
    }

    @PUT
    public void saveCountry saveCountry(Country country) {
        // UPDATE REFERENCES
        country.setRegion(em.getReference(Region.class, country.getRegionId()));
        em.persist(country);
    }

}

你有别的建议吗?

谢谢,

F.D

1 个答案:

答案 0 :(得分:3)

我发现使用DTO pattern作为&#34;反腐败层&#34;通常是个好主意。以及一种用于Web请求/响应主体的已发布API。

例如,让我们上您的国家课程。如果您的Web API直接向下发送Country类(直接序列化为JSON),则会暴露您的Web API消费者可能不应该知道的应用程序代码的一部分,以防止他们编写与这些点相关联的代码。容易发生变化。

所以你建立一个&#34;属性包&#34;作为共同语言和#34;的表示而存在的类您的Web API使用者和协作者应该使用。

例如:

public class CountryDTO {
    public final Integer id;
    public final String countryName;
    public final Integer regionId;

    public CountryDTO(Country countryToSerialize){
        this.id = countryToSerialize.getId();
        this.countryName = countryToSerialize.getCountryName();
        this.regionId = countryToSerialize.getRegion().getId();
    }
}

这样,如果您将来更改Country类的结构,您的API使用者仍会看到相同的一致数据&#34; shape&#34; (根据您的版本控制惯例,您不得弃用/升级/更新)。

您还可以对域对象的序列化方式进行细粒度的,与库无关的控制,因为您可以选择使用哪些字段。

最后,您不必担心从请求中提取实体对象,以及您的ORM是否认为它们是附加/未连接/瞬态/您在应用程序代码中传递它们时的混淆。然后,您可以在实例化域实体之前,根据严格瞬态DTO自由添加验证步骤。