JPA/ hibernate/PostgresDB and Vaadin 8: SQL select query to get data from inherited tables and show in Vaadin grid

JPA/ hibernate/PostgresDB and Vaadin 8: SQL select query to get data from inherited tables and show in Vaadin grid

我正在使用带有 Java/hibernate/JPA 和 postgres 数据库的 Vaadin 8。我想从不同的 table 中获取数据到我的 Vaadin 网格中。我的数据库模型中的相关部分如下所示:

Compound.java 看起来像:

@Entity
@Table(name = "\"Compound\"")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
public abstract class Compound {

@Id
@GeneratedValue
@Column(name = "id", nullable = false)
private UUID id;

@Column(name = "\"specialName\"", unique = true, nullable = false)
private String specialName;

@Column(name = "\"dateAdded\"", nullable = false)
private LocalDate dateAdded;

@OneToOne(mappedBy = "compound", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private StructureData structureData;

//Getter and setter are omitted here

}

Probe.java class:

@Entity(name = "\"Probe\"")
@Table(name = "\"Probe\"")
@PrimaryKeyJoinColumn(name = "\"compoundId\"")
@DiscriminatorValue(value = "probe")
public class Probe extends Compound {

@Column(name = "\"targetProteinFamily\"", length = 150, nullable = false)
private String targetProteinFamily;

@Column(name = "\"probeClass\"", length = 150, nullable = false)
private String probeClass;

@OneToMany(mappedBy = "probe", cascade = CascadeType.ALL, orphanRemoval = true)
private List<NegativeControl> controls;

  //Getter and setter are omitted 
} 

NegativeControl.java

@Entity(name = "\"NegativeControl\"")
@Table(name = "\"NegativeControl\"")
@PrimaryKeyJoinColumn(name = "\"compoundId\"")
@DiscriminatorValue(value = "control")
public class NegativeControl extends Compound {

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="\"probeId\"")
private Probe probe;

}

StructureData.java

@Entity(name = "\"StructureData\"")
@Table(name = "\"StructureData\"")
public class StructureData {

@Id
private UUID id;

@Column(name = "\"smilesCode\"", columnDefinition = "TEXT")
private String smilesCode;

@Column(name = "\"sdFileName\"", length = 255)
private String sdFileName;

@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Compound compound;

}

仅来自探测器 table 的数据的 select 运行良好,数据显示在我的 Vaadin 网格中:

List<Probe> allProbes = entityManager.createQuery("select p from " + Probe.class.getName() + " p").getResultList();

并且在视图中 class:

 grid.setColumns("specialName", "probeClass", "targetProteinFamily");

但我还需要显示来自 StructureData 的数据和来自 NegativeControl 的特殊名称。我尝试了许多不同的 select 语句,但总是出现休眠错误。部分错误版本(只是为了从StructureData获取数据)如下:

List<Probe> allProbes = entityManager.createQuery("select p , s from " + Probe.class.getName() + " p, " + StructureData.class.getName() + " s where type(p) = probe and Compound.id = s.compound_id").getResultList();
List<Probe> allProbes = entityManager.createQuery("select p , s from " + Probe.class.getName() + " p, " + StructureData.class.getName() + " s where type(p) = probe").getResultList();

第一个 select 的错误是:

SEVERE: 
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: ''Compound'.id' [select p , s from sgc.chemprobesapp.core.model.Probe p, sgc.chemprobesapp.core.model.StructureData s where type(p) = probe and Compound.id = s.compound_id]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:131)

我正在寻找有效的 select 语句和 Vaadin grid.setColumns 代码。

感谢您的帮助!

编辑: 我解决了问题的 sql 部分。以下查询正在获取所需的数据:

List<Probe> allProbes = entityManager
            .createQuery("select p from sgc.chemprobesapp.core.model.Probe p "
                    + "left join fetch p.controls c left join fetch p.structureData s", Probe.class)
            .getResultList();

但是我的第二部分是Vaadin8网格问题。我不知道如何直接设置不是 Probe 列而是 StructureData 列的所需列。

grid.setColumns("specialName", "probeClass", "targetProteinFamily",  "structureData.sdFileName");

这似乎有效。但我想用我的标题设置列,例如

grid.addColumn(Probe::getSpecialName).setCaption("Name");
grid.addColumn(Probe::getTargetProteinFamily).setCaption("Target protein family");
grid.addColumn(Probe::getProbeClass).setCaption("Probe class");
grid.addColumn(Probe::getStructureData::getSdFileName).setCaption("Structure");

但是Probe::getStructureData给出错误"The target type of this expression must be a functional interface"。

我希望有人能帮我解决这个问题。谢谢!

我终于知道怎么做了。我 post 的答案,以防其他人有同样的问题需要解决。

如上述编辑中所述,查询为:

List<Probe> allProbes = entityManager
        .createQuery("select p from sgc.chemprobesapp.core.model.Probe p "
                + "left join fetch p.controls c left join fetch p.structureData s", Probe.class)
        .getResultList(); 

在Vaadin 8 grid中显示来自不同数据库表的数据可以按如下方式完成:

private Grid<Probe> grid = new Grid<>(Probe.class);
grid.removeAllColumns();
grid.addColumn(probe -> probe.getSpecialName()).setCaption("Name");
grid.addColumn(probe -> probe.getTargetProteinFamily()).setCaption("Target protein family");
grid.addColumn(probe -> probe.getClass()).setCaption("Class");
grid.addColumn(probe -> probe.getStructureData().getSdFileName()).setCaption("Structure"); 
grid.addColumn(probe -> probe.getNegativeControl().get(0).getSpecialName()).setCaption("Negative control");
grid.setItems(allProbes);

我必须先删除所有列,因为显示了所有继承表的列。变量 allProbes 是我从上面的数据库查询中得到的探测器列表。