Ответ 1
Я собираюсь предложить здесь своеобразное мнение.
Свойства JavaFX и JPA
Как я прокомментировал ответ jewelsea, использование JavaFX на основе свойств bean с JPA возможно, если вы используете "доступ к свойствам", а не "доступ к полю". сообщение в блоге. Я связал здесь более подробно об этом, но основная идея заключается в том, что любые аннотации должны быть в методах get...()
, а не на полях. Насколько я вижу, это предотвращает использование каких-либо свойств свойств JavaFX только для чтения в сочетании с JPA, но я никогда не чувствовал, что JPA хорошо играет с свойствами только для чтения (т.е. Получать методы и не устанавливать метод) в любом случае.
Сериализация
В отличие от моего комментария на jewelsea answer и с помощью нескольких недель для работы с этим (и будучи помещенным в положение, когда мне пришлось реплицировать несколько классов сущностей на стороне клиента JavaFX с использованием свойств JavaFX), я что отсутствие сериализации свойств JavaFX можно обойти. Главное наблюдение заключается в том, что вам действительно нужно только сериализовать обернутое состояние свойства (не, например, любых слушателей). Вы можете сделать это, выполнив java.io.Externalizable
. Externalizable
- это суб-интерфейс Serializable
, который требует, чтобы вы заполнили методы readExternal(...)
и writeExternal(...)
. Эти методы могут быть реализованы для экстернализации только состояния, завершенного свойством, а не самого свойства. Это означает, что если ваша сущность сериализована и затем десериализована, вы получите новый экземпляр свойства, и никакие слушатели не будут сохранены (т.е. слушатели фактически станут transient
), но насколько я вижу, это будет что было необходимо в любом разумном случае.
Я экспериментировал с beans таким образом, и все это, похоже, работает хорошо. Кроме того, я провел небольшой эксперимент по передаче их между клиентом и успокоительной веб-службой, используя картографию Jackson для преобразования в представление JSON и из него. Поскольку mapper просто полагается на использование методов 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());
}
}