我正在尝试使用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;
}
我想为客户提供以下基本操作:
password
joinedAt
和password
joinedAt
或password
我目前的(1)解决方案是将@XmlTransient添加到密码字段。如果要将密码发送给某些客户端而不是其他客户端,则会出现问题。另一种解决方案是在通过编组该实体之前执行customer.setPassword(null);
网络服务。但这真的是这样做的方式吗?第三种解决方案是创建一个基类BaseCustomer
,其中包含除password
之外的所有字段,然后客户将是BaseCustomer
,其中添加了password
字段。用户将收到BaseCustomer对象而不是Customer对象。但这也存在创建/更新问题。
与(1)相同,当客户想要创建新客户时,一个解决方案是customer.setJoinedAt(my_value); customer.setPassword(my_value); customer.setId(null);
。手动归零id
真的最佳做法?我觉得很难相信。 id
也应该是XmlTransient吗?但那么Web服务的用户将如何修改/删除实体?
当客户想要更改Customer
时,他会检索客户列表,对其中一个Customer
对象进行更改,然后整理该对象并将其传递回网络服务。
这有一些问题:如果id
字段是XmlTransient,那么EntityManager的持久化将不知道要修改哪一行,并且可能会创建一个新行。如果用户是邪恶的并且只是拒绝传递id
,则会出现类似的问题,因此我必须手动检查id
是否为空。此外,用户尚未收到password
字段,因此现在服务器已收到一个具有空password
字段的对象,它将尝试保留该字段。我相信这会导致EntityManager完全删除现有Customer的密码。让用户准确指定他想要修改的字段以及哪些值似乎不切实际。
请注意,这只是我需要做的概念验证,我需要提供更多的实体,关系和操作。
我是使用这些技术的新手,我希望如此高水平,并且拥有如此多的抽象将使我的生活更轻松,但到目前为止,它一直是令人头痛的问题。实现这一共同的基本任务似乎非常困难。难道我做错了什么?请不要建议创建Web应用程序:)