【问题标题】:Displaying column in tableView在 tableView 中显示列
【发布时间】:2019-05-11 11:04:31
【问题描述】:

我正在尝试使用 JavaFX 8 和休眠中的 TableView 映射和显示表之间存在一对一关系的数据。

表格:

@Entity
@Table(name = "CLUB")
public class Club implements Serializable {

    @Id
    @Column(name = "CLUB_ID", nullable = false, unique = true)
    private int clubId;

    @Column(name = "NAME", nullable = false, length = 100)
    private String name;

    @Column(name = "CITY", length = 50)
    private String city;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "club", cascade = CascadeType.ALL)
    private Trainer trainer;

    // constructor, getters, setters
}

@Entity
@Table(name = "TRAINER")
public class Trainer implements Serializable {

    @Id
    @Column(name = "LICENCE_NR", nullable = false, unique = true)
    private int licenceNr;

    @Column(name = "NAME", nullable = false, length = 50)
    private String name;

    @Column(name = "SURNAME", nullable = false, length = 50)
    private String surname;

    @OneToOne(fetch = FetchType.LAZY)
    @PrimaryKeyJoinColumn
    private Club club;

    // constructor, getters, setters
}

ClubController 类与TableView:

public class ClubController implements Initializable {

    ...

    @FXML
    private TableView<Club> clubTableView;

    @FXML
    private TableColumn<Club, String> nameColumn;

    @FXML
    private TableColumn<Club, String> cityColumn;

    @FXML
    private TableColumn<Club, Integer> trainerColumn;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        nameColumn.setCellValueFactory(new PropertyValueFactory<Club, String>("name"));
        cityColumn.setCellValueFactory(new PropertyValueFactory<Club, String>("city"));
        trainerColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Club, Integer>, ObservableValue<Integer>>() {
            @Override
            public ObservableValue<Integer> call(TableColumn.CellDataFeatures<Club, Integer> param) {
                return new SimpleIntegerProperty(param.getValue().getTrainer().getLicenceNr()).asObject();
            }
        });
        clubTableView.setItems(getClub());
    }

    private ObservableList<Club> getClub() {
        ObservableList<Club> clubList = FXCollections.observableArrayList();
        Session session = HibernateUtil.config().openSession();
        List<Club> cList = session.createCriteria(Club.class).list();
        clubList.addAll(cList);
        session.close();
        return clubList;
    }

    ...
}

前两列工作正常,但在trainerColumn 我有 NPE。如何解决?

【问题讨论】:

  • SimpleIntegerProperty 的构造函数将原始的int 值作为参数。这意味着属性不能包含null 值。 (不过,NPE 是可能的。因此,要么问题的描述具有误导性,要么您没有发布重现问题所需的代码......
  • 是的,你是对的,它是 NPE,不是空值。

标签: java hibernate jpa javafx collections


【解决方案1】:

CLUB 实体中的trainer 字段是延迟加载的:

...
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "club", cascade = CascadeType.ALL)
    private Trainer trainer;
...

...只有在创建实体的会话打开时才能读取。

ClubController 中,您打开和关闭了会话,而没有从数据库中显式加载trainer 详细信息:

    private ObservableList<Club> getClub() {
        ObservableList<Club> clubList = FXCollections.observableArrayList();

        // SESSION OPENED
        Session session = HibernateUtil.config().openSession();

        // CLUB ENTITIES LOADED WITH LAZY TRAINERS
        List<Club> cList = session.createCriteria(Club.class).list();
        clubList.addAll(cList);

        //SESSION CLOSED
        session.close();

        return clubList;
    }

所以要么使 CLUB 实体中的 trainer 字段被预先加载:

...
    @OneToOne(fetch = FetchType.EAGER, mappedBy = "club", cascade = CascadeType.ALL)
    private Trainer trainer;
...

或者在查询数据库时显式加载trainer - 使用以下简单的方法:

...
        // SESSION OPENED
        Session session = HibernateUtil.config().openSession();

        // CLUB ENTITIES LOADED WITH LAZY TRAINERS
        List<Club> cList = session.createCriteria(Club.class).list();

        // EXPLICITLY LOAD ALL TRAINERS FROM DB
        cList.stream().peek(club -> club.getTrainer().getLicenceNr())
        clubList.addAll(cList);

        //SESSION CLOSED
        session.close();
...

虽然,我建议不要使用最后一个,因为它有点脏且性能较差(许多额外的往返数据库, 如果急切,而不是对所有一对一记录查询进行单个连接查询);但仍然可用。

【讨论】:

  • 我尝试了两种解决方案。我仍然得到 NullPointerException。
  • 在关闭会话之前调用cList.stream().peek(club -&gt; System.out.println(club.getTrainer().getLicenceNr())) 并确保所有培训师都从数据库加载。如果你在那里得到一个 NPE,那么你有 another 与从数据库加载 trainers 相关的问题,与当前问题无关;需要进行更深入的调试(即很可能某些俱乐部在您的数据库中没有关联trainer
  • 好的,感谢您的提示。我对其他表进行了相同的操作,并且它可以正常工作,因此TrainerClub之间的关系肯定有问题。我会努力找出错误的。
猜你喜欢
  • 2019-02-25
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 2017-08-23
相关资源
最近更新 更多