Utilisation de javafx.propriétés des haricots dans les classes de modèles

est-ce une bonne pratique d'utiliser les propriétés des haricots JavaFX dans les classes de modèles?

je me demande si c'est une bonne pratique d'utiliser des propriétés dans les classes de modèles pour pouvoir les lier plus facilement avec les composants de la vue. Je ne m'inquiète pas de la disponibilité de ces bibliothèques dans le futur parce que mon programme sera lancé sur JRE8 ou plus tard, mais la nature de l'utilisation des bibliothèques JavaFX dans les classes de modèles me rend sceptique et je m'inquiète des incompréhensibles actuelles et futures spécialement parce que je veux utiliser L'hibernation pour persister ces attributs.

Note: j'utilise un environnement JavaFX pur et je n'aurai jamais besoin de compabilité Swing dans mon application.

24
demandé sur Francesco Menzani 2014-04-21 01:52:36

3 réponses

je vais vous donner une opinion dissidente.

JavaFX Propriétés et JPA

comme j'ai commenté la réponse de jewelsea, l'utilisation D'un bean basé sur la propriété JavaFX avec JPA est possible à condition que vous utilisiez "accès à la propriété" plutôt que "accès aux champs". blog j'ai relié là va plus en détail sur ce, mais l'idée de base est que toute annotation devrait être sur le get...() méthodes et pas sur les champs. Aussi loin que je peux vous voyez, cela empêche l'utilisation de n'importe quelle propriété JavaFX en lecture seule en conjonction avec JPA, mais je n'ai jamais vraiment senti JPA bien joué avec les propriétés en lecture seule (i.e. get methods et no set method) de toute façon.

la Sérialisation

contrairement à mon commentaire sur la réponse de jewelsea, et avec le bénéfice de quelques semaines pour travailler avec ceci (et ayant été placé dans une position où je faisais face à la réplique de plusieurs classes d'entités du côté du client JavaFX en utilisant les propriétés JavaFX), je pense que le manque de sérialisation des propriétés JavaFX peut être contourné. L'observation clé est que vous n'avez vraiment besoin que de sérialiser l'état enveloppé de la propriété (pas, par exemple, des auditeurs). Vous pouvez le faire par la mise en œuvre de java.io.Externalizable. Externalizable est une sous-interface de Serializable cela exige que vous remplissiez le readExternal(...) et writeExternal(...) méthodes. Ces méthodes peuvent être mises en œuvre pour externaliser juste l'état Enveloppé par la propriété, plutôt que la propriété m'. Cela signifie que si votre entité est sérialisée puis désérialisée, vous finirez avec une nouvelle instance de propriété, et les écouteurs ne seront pas préservés (c'est-à-dire que les écouteurs deviendront effectivement transient), mais pour autant que je puisse voir que ce serait ce qu'on voulait dans n'importe quel cas d'utilisation raisonnable.

j'ai expérimenté avec des haricots définis de cette façon et tout semble fonctionner bien. De plus, j'ai fait une petite expérience en les transférant entre le client et un service web reposant, en utilisant le Jackson mappeur pour convertir une représentation JSON. Depuis le mappeur juste s'appuie sur l'utilisation des méthodes get et set, cela fonctionne bien.

Quelques mises en garde

quelques points doivent être observés. Comme pour toute sérialisation, il est important d'avoir un constructeur sans argument. Et bien sûr, toutes les valeurs enveloppées par les propriétés JavaFX doivent elles - mêmes être sérialisables-encore une fois c'est la même règle que pour toute sérialisable haricot.

le point sur les propriétés JavaFX travaillant via des effets secondaires est bien pris, et il faut être prudent lors du déplacement de ces propriétés (qui sont, dans une certaine mesure, conçues avec un modèle mono-threadé à l'esprit) vers un serveur potentiellement multi-threadé. Une bonne règle empirique est probablement que si vous utilisez cette stratégie, les écouteurs ne devraient être enregistrés que du côté client (et rappelez - vous, ces écouteurs sont transitoires en ce qui concerne le transfert vers le serveur, que ce soit par la sérialisation ou par représentation JSON). Bien sûr, cela suggère que l'utilisation de ceux-ci du côté du serveur pourrait alors être une mauvaise conception; il devient un compromis entre la commodité d'avoir une entité unique qui est "tout pour tous les gens" (propriétés observables pour le client JavaFX, sérialisable pour la persistance et/ou l'accès à distance, et avec des mappages persistants pour JPA) versus exposer la fonctionnalité (par exemple observabilité) où il pourrait ne pas être entièrement approprié (sur le serveur.)

enfin, si vous utilisez les annotations JPA, celles - ci ont une rétention d'exécution qui implique (je pense) que votre client JavaFX aura besoin de l'a javax.la persistance de la spécification dans le classpath).

Voici un exemple d'un tel "homme pour toutes les saisons" entité:

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());
    }

}
18
répondu James_D 2014-05-07 20:35:00

JavaFX Propriété De Conception

Les propriétés JavaFX sont conçues de telle sorte que vous n'avez pas besoin d'exécuter un programme JavaFX pour les utiliser. Les sections de la Oracle à l'Aide de JavaFX et Propriétés de Liaison Tutoriel, démontre une telle utilisation (par exemple une classe de facture pour modéliser les propriétés d'une facture). L'exemple du tutoriel ne fait qu'exécuter un programme Java standard avec un main et pas JavaFX Application. Vous pouvez donc utiliser les propriétés de manière générique. sans avoir d'exigence supplémentaire sur le JavaFX runtime. Cela signifie que vous pouvez, par exemple, utiliser les propriétés JavaFX et les fixations dans une application côté serveur.

"Corriger" Les Pratiques

OK, donc vous pouvez le faire, mais est-ce" correct " pratique?

Je ne pense pas que beaucoup de gens utilisent les propriétés JavaFX de cette façon. Une raison pour cela est simplement parce que les propriétés JavaFX sont tout à fait nouvelles. Je ne pense pas que c'est "mal" à utiliser Propriétés JavaFX dans les objets model.

mises en garde

Les propriétés JavaFX ne supportent pas la sérialisation Java (par ceci je veux dire le support direct pour le Serialisable interface). De nombreuses technologies Java côté serveur pourraient nécessiter une sérialisation de modèle et ils seraient incapables de sérialiser n'importe quel objet qui a fait usage des propriétés JavaFX.

Les propriétés JavaFX elles-mêmes ne sont pas sensibles aux containers et agissent par le biais d'effets secondaires (E. g changer a la propriété peut déclencher une mise à jour à une autre valeur liée), alors soyez conscient de cela et assurez-vous que ce type de traitement est une approche acceptable dans votre environnement. En particulier, faites attention à ne pas générer de conditions de course indésirables dans un environnement de serveur multi-threadé (les applications client JavaFX nécessitent généralement moins de soin à cet égard, car JavaFX fonctionne généralement comme un seul environnement threadé).

JavaFX Propriétés et Hibernate/JPA

Je ne pense pas que mélanger les propriétés JavaFX dans les classes d'entités Hibernate (ou JPA) soit une bonne idée. Je n'ai pas vu quelqu'un le faire. Hibernate lui-même n'est pas au courant des propriétés JavaFX et en général est conçu pour fonctionner contre les primitives Java comme les chaînes et les ints, donc je ne sais pas comment il pourrait éventuellement cartographier automatiquement une propriété JavaFX à un champ de base de données.

vous auriez probablement besoin d'une configuration qui définisse votre hiérarchie de classe d'entity et un une hiérarchie parallèle pour vos classes de modèles basées sur les propriétés JavaFX et enfin une couche mapper qui correspond à la correspondance entre les deux. Ce type de configuration architecturale est essentiellement un MVVM model. Le model (M) est votre classe d'entity Hibernate, et le view model (VM) est votre Model basé sur les propriétés JavaFX.

8
répondu jewelsea 2014-04-20 23:30:37

pour les collections jpa persisting il suffit d'utiliser cette signature pour la méthode getter..

@OneToMany
List<Person> getAll()
{
return observableList;
}
0
répondu user2768310 2015-01-19 10:41:30