java - 在模型类中使用 javafx.beans 属性

标签 java hibernate javafx model persistence

在模型类中使用 JavaFX bean 属性是否正确?

我想知道在模型类中使用属​​性以便能够更轻松地将它们与 View 组件绑定(bind)是否是一种好习惯。我不担心将来这些库的可用性,因为我的程序将在 JRE8 或更高版本上运行,但是在模型类中使用 JavaFX 库的性质让我持怀疑态度,我特别担心当前和 future 的不兼容性,因为我想使用 Hibernate 来持久化这些属性。

注意:我使用的是纯 JavaFX 环境,我的应用程序永远不需要 Swing 兼容性。

最佳答案

我将在这里提出一些不同的意见。

JavaFX 属性和 JPA

正如我对jewelsea 的回答所评论的那样,只要您使用“属性访问”而不是“字段访问”,就可以将基于JavaFX 属性的bean 与JPA 结合使用。 blog post我在此处链接对此进行了更详细的说明,但基本思想是任何注释都应该在 get...() 方法上,而不是在字段上。据我所知,这确实阻止了将任何只读 JavaFX 属性模式与 JPA 结合使用,但我从来没有真正觉得 JPA 与只读属性(即 get 方法和无 set 方法)配合得很好.

序列化

与我对 Jewelsea 的回答的评论相反,并且有几个星期的时间来处理这个问题(并且已经被放置在我面临使用 JavaFX 属性在 JavaFX 客户端复制多个实体类的位置),我认为可以解决 JavaFX 属性缺乏序列化的问题。关键的观察是您实际上只需要序列化属性的包装状态(例如,不需要任何监听器)。您可以通过实现 java.io.Externalizable 来做到这一点。 ExternalizableSerializable 的子接口(interface),需要你填写 readExternal(...)writeExternal(.. .) 方法。可以实现这些方法以仅将属性包装的状态外部化,而不是属性本身。这意味着如果您的实体被序列化然后反序列化,您最终将得到一个新的属性实例,并且不会保留任何监听器(即监听器实际上变为 transient),但就我而言可以看到这将是任何合理用例中想要的。

我尝试了以这种方式定义的 bean,并且一切似乎都运行良好。此外,我进行了一个小型实验,在客户端和一个 RESTful Web 服务之间传输它们,使用 Jackson 映射器在 JSON 表示形式之间进行转换。由于映射器仅依赖于使用 get 和 set 方法,因此可以正常工作。

一些注意事项

需要注意几点。与任何序列化一样,有一个无参数的构造函数很重要。当然,JavaFX 属性包装的所有值本身都必须是可序列化的——这与任何可序列化 bean 的规则相同。

关于通过副作用工作的 JavaFX 属性的观点已经得到很好的理解,并且在将这些属性(在某种程度上,在设计时考虑到单线程模型)移动到潜在的多线程时需要小心谨慎。线程服务器。一个好的经验法则可能是,如果您使用此策略,监听器应该只在客户端注册(请记住,这些监听器在传回服务器方面是暂时的,无论是通过序列化还是通过 JSON 表示)。当然,这表明在服务器端使用这些可能是一个糟糕的设计。它成为了一个单一实体的便利性,即“所有人的所有事物”(JavaFX 客户端的可观察属性,可序列化以用于持久性和/或远程访问,以及具有 JPA 的持久性映射)与公开功能之间的权衡(例如可观察性)可能不完全合适的地方(在服务器上)。

最后,如果您确实使用了 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());
    }

}

关于java - 在模型类中使用 javafx.beans 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23187989/

相关文章:

java - 什么是 package-info.java,如何将它添加到我的项目中?

java - 如何从 Tableview 迭代数据以将其导出到 Microsoft Excel?

java - hibernate validator 不适用于 Spring MVC 应用程序

java - 当数据库中存在更多行时,ResultSet 仅返回一行

java - FragmentPagerAdapter 未从 getItem 返回正确的 View

java - JPA id 生成通用策略

javascript - 将 json 从 js 传递到 java 的 url 问题

java - Eclipse(Java 和 Hibernate)内容助手不工作

java - 替换 JavaFX 中的列排序

java - javafx中的新手切换按钮事件