在模型类中使用javafx.beans属性
在模型类中使用JavaFX bean属性是否正确?
我想知道在模型类中使用属性是否能够将它们与视图组件轻松绑定是否是一种好习惯。我不担心将来这些库的可用性,因为我的程序将在JRE8或更高版本上运行,但是在模型类中使用JavaFX库的性质使我持怀疑态度,并且我担心当前和将来的不兼容性,尤其是因为我想使用Hibernate来保留这些属性。
注意:我使用纯JavaFX环境,并且我的应用程序永远不需要Swing兼容性。
回答:
我将在这里提出不同意见。
正如我评论jewelsea的答案一样,只要您使用“属性访问”而不是“字段访问”,就可以在JPA中使用基于JavaFX属性的Bean。我链接到那里的博客文章对此进行了更详细的介绍,但是基本思想是任何注释都应该在get...()
方法上,而不是在字段上。据我所知,这确实阻止了将任何只读JavaFX属性模式与JPA结合使用,但是我从来没有真正感觉到JPA在只读属性(即get方法和无set方法)中表现良好。
与我对jewelsea答案的评论相反,并受益于几个星期的工作(并且被安排为我面临使用JavaFX属性在JavaFX客户端上复制多个实体类的位置),我认为缺乏JavaFX属性的序列化可以解决。关键的观察结果是,您实际上只需要序列化属性的包装状态(而不是任何侦听器)。您可以通过实现java.io.Externalizable
。Externalizable
是的子接口Serializable
,要求您填写readExternal(...)
和writeExternal(...)
方法。可以实现这些方法以仅外部化属性包装的状态,而不是属性本身。这意味着,如果您的实体先序列化然后反序列化,您将得到一个新的属性实例,并且将不会保留任何侦听器(即,侦听器实际上变为transient
),但是据我所知,这就是所需要的在任何合理的用例中。
我尝试用这种方式定义的bean,并且一切似乎都很好地工作。另外,我进行了一个小实验,使用杰克逊映射器在JSON表示形式之间进行转换,从而在客户端和静态Web服务之间传输它们。由于映射器仅依靠使用get和set方法,因此可以正常工作。
需要注意两点。与任何序列化一样,拥有无参数的构造函数也很重要。当然,由JavaFX属性包装的所有值本身必须可序列化-
再次,这与任何可序列化bean的规则相同。
关于JavaFX属性通过副作用起作用的观点已被很好地理解,并且在将这些属性(在某种程度上考虑到单线程模型的设计)移至潜在的多线程服务器时,需要格外小心。一个好的经验法则可能是,如果您使用此策略,则仅应在客户端注册侦听器(请记住,这些侦听器是暂时的,无论是通过序列化还是通过JSON表示,都可以传输回服务器)。当然,这表明在服务器端使用它们可能是一个糟糕的设计。在拥有“所有人的万事万物”的单个实体(JavaFX客户端的可观察属性,可序列化以实现持久性和/或远程访问,
最后,如果您确实使用了JPA批注,则这些批注具有运行时保留,这意味着(我认为)您的JavaFX客户端将需要在类路径上使用javax.persistence规范。
这是一个“四季皆宜的人”实体的示例:
import java.io.Externalizable;import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.time.MonthDay;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
* Entity implementation class for Entity: Person
*
*/
@Entity
public class Person implements Externalizable {
private static final long serialVersionUID = 1L;
public Person() {
}
public Person(String name, MonthDay birthday) {
setName(name);
setBirthday(birthday);
}
private final IntegerProperty id = new SimpleIntegerProperty(this, "id");
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id.get();
}
public void setId(int id) {
this.id.set(id);
}
public IntegerProperty idProperty() {
return id ;
}
private final StringProperty name = new SimpleStringProperty(this, "name");
// redundant, but here to indicate that annotations must be on the property accessors:
@Column(name="name")
public final String getName() {
return name.get();
}
public final void setName(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name ;
}
private final ObjectProperty<MonthDay> birthday = new SimpleObjectProperty<>();
public final MonthDay getBirthday() {
return birthday.get();
}
public final void setBirthday(MonthDay birthday) {
this.birthday.set(birthday);
}
public ObjectProperty<MonthDay> birthdayProperty() {
return birthday ;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(getId());
out.writeObject(getName());
out.writeObject(getBirthday());
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
setId(in.readInt());
setName((String) in.readObject());
setBirthday((MonthDay) in.readObject());
}
}
以上是 在模型类中使用javafx.beans属性 的全部内容, 来源链接: utcz.com/qa/414289.html