我正在GWT + Hibernate项目中面临设计决策。
我将使用公司实体解释我的问题。
@Entity
@Table(name = "Company")
public class Company extends LightEntity implements BaseSerializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private int id;
@Column(name = "Code")
private String code;
@Column(name = "Name")
private String name;
@Column(name = "Address")
private String address;
@Column(name = "ContactNumber1")
private String contactNumber1;
@Column(name = "ContactNumber2")
private String contactNumber2;
@Column(name = "EMail")
private String email;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "company", cascade = CascadeType.ALL)
private List<CompanyRegistration> companyRegistrations = new ArrayList<CompanyRegistration>();
public Company() {
}
public Company(String code, String name) {
this.setCode(code);
this.setName(name);
}
// getters & setters
}
有效的公司对象必须始终具有有效的代码和名称。其余属性是可选的。因此,我提供了一个双参数构造函数来确保创建一个有效的对象。
现在
我习惯于在setter中验证数据。我也在构造函数中使用这些setter。这些确保新对象始终具有有效状态。这是我实现Hibernate实体的计划。
但是,GWT-RPC要求默认的noargs构造函数,以便它可以用于延迟绑定。但这也将允许任何人创建一个空对象,这在我的大多数Hibernate实体中都是不可取的。例如,公司必须始终使用代码和名称构建。 noargs构造函数违反了该规则。
现在,Hibernate已经为验证框架实现了一个标准(JSR-303,如果我的记忆不会背叛我)。它允许您在已创建的对象上调用验证。
由于noargs构造函数,我的问题出现了。如果它不是强制性的,我会在setter中废除验证。
如果我在setter中实现验证,则意味着无效对象将尽快失败。我不需要在客户端上调用对象的验证。但是,无法以这种方式验证空对象(使用noargs构造函数创建)。它可能会影响服务,这意味着我还必须在服务层中实现验证,其中很多可能与setter相同。
如果我实现验证框架,那么我必须对我在客户端创建的每个对象调用验证。如果我忘记验证一个,它可以在无效状态下进入服务层。但是,我可以轻松地在服务层上使用相同的框架。
我想到的一个解决方案是无论如何都要在setter中实现验证,但在发送一个对象以在数据库中持久化之前,还要在服务层中使用Validator。这样,客户端将自动受到设置者的限制。另一方面,如果无论如何将空对象发送到服务器端,它将被服务层上的Validator捕获。在这两种情况下都会向用户抛出异常。
但我认为这不是最好的解决方案。所以,我想得到一个。
编辑 - 我总是使用注释来对实体字段设置约束,以便Hibernate在持久化对象之前可以使用它们进行验证。
答案 0 :(得分:1)
如果您的问题仅源于GWT-RPC的强制零参数构造函数,请注意您可以使开发人员无法访问此构造函数(如果需要,甚至可以private
); GWT-RPC将使用反射来访问它,无论其可见性如何。