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 是我从上面的数据库查询中得到的探测器列表。
我正在使用带有 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 是我从上面的数据库查询中得到的探测器列表。