Java 使用JAX-WS向客户机提供实体

Java 使用JAX-WS向客户机提供实体,java,jpa,jax-ws,Java,Jpa,Jax Ws,我正在尝试使用JAX-WS(SOAP)创建一个web服务,允许对某些实体执行CRUD操作。我还编写了一个带有UI的桌面客户端,它提供了通过web服务在这些实体上执行CRUD的简单方法 然而,我遇到了一些设计问题。我希望客户端只能查看和操作实体的某些字段,我不确定施加此限制的最佳方式是什么 例如,假设: @Entity public class Customer { @Id @GeneratedValue public Long id; public String name;

我正在尝试使用JAX-WS(SOAP)创建一个web服务,允许对某些实体执行CRUD操作。我还编写了一个带有UI的桌面客户端,它提供了通过web服务在这些实体上执行CRUD的简单方法

然而,我遇到了一些设计问题。我希望客户端只能查看和操作实体的某些字段,我不确定施加此限制的最佳方式是什么

例如,假设:

@Entity
public class Customer {

  @Id
  @GeneratedValue
  public Long id;

  public String name;

  // neither read nor write from the web service
  public String password;

  // read-only from the web service
  @Temporal(TemporalType.DATE)
  public Date joinedAt;

  @ManyToOne
  @LazyCollection(LazyCollectionOption.FALSE)
  private List<Order> orders;

  // .. boilerplate getters and setters
}

@Entity
public class Order {

  @Id
  @GeneratedValue
  public Long id;

  public String name;
}
@实体
公共类客户{
@身份证
@生成值
公共长id;
公共字符串名称;
//既不从web服务读取也不从web服务写入
公共字符串密码;
//从web服务只读
@时态(TemporalType.DATE)
公开日期联合日期;
@许多酮
@LazyCollection(LazyCollectionOption.FALSE)
私人名单订单;
//..样板间的接受者和接受者
}
@实体
公共阶级秩序{
@身份证
@生成值
公共长id;
公共字符串名称;
}
我想向客户提供以下基本操作:

  • 获取所有客户的订单列表
    • 他可以看到除密码之外的所有字段
  • 使用一些订单创建新客户
    • 允许对所有字段进行控制,除了
      joinedAt
      password
  • 修改客户
    • 同上,不允许修改
      joinedAt
      密码
  • 我目前针对(1)的解决方案是在密码字段中添加@xmltransive。如果您想将密码发送给某些客户机,而不是其他客户机,则这是有问题的。另一个解决方案是执行
    customer.setPassword(null)在通过编组该实体之前
    网络服务。但这真的是这样吗?第三种解决方案是创建一个基类
    BaseCustomer
    ,它包含除
    password
    之外的所有字段,然后Customer将是一个
    BaseCustomer
    ,并添加了
    password
    字段。用户将接收BaseCustomer对象,而不是Customer对象。但这在创建/更新方面也存在问题

  • 与(1)相同,一种解决方案是执行
    customer.setJoinedAt(my_值);customer.setPassword(我的值);customer.setId(空)当客户想要创建新客户时。手动清空
    id
    真的是最佳实践吗?我觉得很难相信。
    id
    也应该是瞬时的吗?但是,web服务的用户如何能够修改/删除实体呢

  • 当客户机想要更改
    客户
    时,他检索客户列表,对其中一个
    客户
    对象进行更改,然后封送该对象并将其传递回web服务。 这有几个问题:如果
    id
    字段是XmlTransient,那么EntityManager的persist将不知道要修改哪一行,并且可能会创建一个新的行。如果用户是邪恶的,只是拒绝传递
    id
    ,则会出现类似的问题,因此我必须手动检查
    id
    是否为非空。此外,用户还没有收到
    密码
    字段,因此现在服务器收到了一个带有空
    密码
    字段的对象,它将尝试保留该字段。我相信这将导致EntityManager完全删除现有客户的密码。让用户精确地指定他想要修改的字段和值似乎不切实际

  • 请注意,这只是我需要做的概念证明。简而言之,我有更多的实体、关系和操作要提供


    我对使用这些技术还不熟悉,我希望如此高的水平和如此多的抽象将使我的生活更轻松,但到目前为止,这主要是令人头痛的。似乎很难完成这项共同的基本任务。我做错什么了吗?请不要建议创建web应用程序:)

    我建议不要通过soap将对象作为实体传输。考虑使用传输对象:从实体到映射对象的映射数据。但是这不会导致大量的代码复制吗?或者实体会继承传输对象吗?另外,我是否需要手动编写大量的
    entityobj.setField(transferobj.getField())
    来从一个转换到另一个?这样可以吗?如果问题域不同,那么拥有两行相同的代码不应被视为代码重复-正确使用传输对象可以并且将使代码更加冗长。对于实体,您仅限于以下操作:getCustomer()和getCustomerOrders(),而对于传输对象,您可以编写具有业务意义的操作,例如:getCustomerDetails()和getCustomerDetailsWithOrderSummary()。是的,您将不得不手动编写大量映射代码-这完全可以。考虑为映射创建单独的类。