简体   繁体   English

Hibernate继承与hibernate标准(TABLE_PER_CLASS)

[英]Hibernate inheritance with hibernate criteria (TABLE_PER_CLASS)

I have a Cell with list of widgets. 我有一个包含小部件列表的Cell。 Widgets is an abstract entity and it is used to store common attributes with all future Entities like button, search, criteria etc.. Please do not think about ClassNamed interface - it has no impact on my result - I checked it twice. 窗口小部件是一个抽象实体,它用于存储所有未来实体的常见属性,如按钮,搜索,条件等。请不要考虑ClassNamed接口 - 它对我的结果没有影响 - 我检查了两次。

Cell (with list of Widgets): 单元格(包含小部件列表):

@Entity
@Table(name = "DASHBOARD_CELL")
public class DashboardCell {

    private Integer id;
    private Integer rowPosition;
    private Integer columnPosition;
    private Integer columnWeight;
    private DashboardBox dashboardBox;
    private List<DashboardWidget> dashboardWidgets;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "ROW_POSITION")
    public Integer getRowPosition() {
        return rowPosition;
    }

    public void setRowPosition(Integer rowPosition) {
        this.rowPosition = rowPosition;
    }

    @Column(name = "COLUMN_POSITION")
    public Integer getColumnPosition() {
        return columnPosition;
    }

    public void setColumnPosition(Integer columnPosition) {
        this.columnPosition = columnPosition;
    }

    @Column(name = "COLUMN_WEIGHT")
    public Integer getColumnWeight() {
        return columnWeight;
    }

    public void setColumnWeight(Integer columnWeight) {
        this.columnWeight = columnWeight;
    }

    @ManyToOne(optional = false, fetch=FetchType.LAZY)
    @JoinColumn(name="DASHBOARD_BOX_ID")
    @JsonBackReference
    public DashboardBox getDashboardBox() {
        return dashboardBox;
    }

    public void setDashboardBox(DashboardBox dashboardBox) {
        this.dashboardBox = dashboardBox;
    }

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "dashboardCell", fetch=FetchType.EAGER)
    @JsonManagedReference
    public List<DashboardWidget> getDashboardWidgets() {
        return dashboardWidgets;
    }

    public void setDashboardWidgets(List<DashboardWidget> dashboardWidgets) {
        this.dashboardWidgets = dashboardWidgets;
    }

}

Widget: 小工具:

@Entity
@Table(name = "DASHBOARD_WIDGET")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class DashboardWidget implements ClassNamed{

    private Integer id;
    private String title;
    private Integer backgroundColor;
    private Integer orderNumber;
    private DashboardCell dashboardCell;
    private String widgetType = getWidgetType();

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name = "ID")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "TITLE")
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Column(name = "BACKGROUND_COLOR_VALUE")
    public Integer getBackgroundColor() {
        return backgroundColor;
    }

    public void setBackgroundColor(Integer backgroundColor) {
        this.backgroundColor = backgroundColor;
    }

    @Column(name = "ORDER_NUMBER")
    public Integer getOrderNumber() {
        return orderNumber;
    }

    public void setOrderNumber(Integer orderNumber) {
        this.orderNumber = orderNumber;
    }

    @ManyToOne(optional = false)
    @JoinColumn(name = "DASHBOARD_CELL_ID")
    @JsonBackReference
    public DashboardCell getDashboardCell() {
        return dashboardCell;
    }

    public void setDashboardCell(DashboardCell dashboardCell) {
        this.dashboardCell = dashboardCell;
    }

    public String getWidgetType() {
        return getClassName();
    }

    public void setWidgetType(String widgetType) {
        this.widgetType = widgetType;
    }
}

CriteriaWidget: CriteriaWidget:

@Entity
@Table(name = "DASHBOARD_CRITERIA")
public class DashboardCriteria extends DashboardWidget {
    private Integer value;
    private Integer maximumValue;

    @Column(name = "ACTUAL_VALUE")
    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    @Column(name = "MAX_VALUE")
    public Integer getMaximumValue() {
        return maximumValue;
    }

    public void setMaximumValue(Integer maximumValue) {
        this.maximumValue = maximumValue;
    }

    @Transient
    @Override
    public String getClassName() {
        return DashboardCriteria.class.getName();
    }

}

When I try to query all cells with widgets using following code: 当我尝试使用以下代码查询具有小部件的所有单元格时:

sessionFactory.getCurrentSession().createCriteria(DashboardCell.class).list();

I got 4 records: 1 Cell with 4 Criterias, 1 (same cell) with 4 criterias, 1 (same cell) with 4 Criterias, 1 (same cell) with 4 Criterias. 我有4条记录:1个细胞有4个标​​准,1个(相同细胞)有4个标准,1个(相同细胞)有4个标准,1个(相同细胞)有4个标准。 What I have in database is 1 cell with 4 DashBoardCriteria's (H2 database): 我在数据库中有1个单元格,有4个DashBoardCriteria(H2数据库):

insert into DASHBOARD_CELL (ID, ROW_POSITION, COLUMN_POSITION, COLUMN_WEIGHT, DASHBOARD_BOX_ID) values (100, 0, 0, 12, 6);

insert into DASHBOARD_CRITERIA (ID, TITLE, BACKGROUND_COLOR_VALUE, ORDER_NUMBER, DASHBOARD_CELL_ID, ACTUAL_VALUE, MAX_VALUE) values (200, 'Registered', 16769408, 0, 100, 21, 30);
insert into DASHBOARD_CRITERIA (ID, TITLE, BACKGROUND_COLOR_VALUE, ORDER_NUMBER, DASHBOARD_CELL_ID, ACTUAL_VALUE, MAX_VALUE) values (201, 'Completed', 11723766, 1, 100, 22, 30);
insert into DASHBOARD_CRITERIA (ID, TITLE, BACKGROUND_COLOR_VALUE, ORDER_NUMBER, DASHBOARD_CELL_ID, ACTUAL_VALUE, MAX_VALUE) values (202, 'Approved', 11921353, 2, 100, 5, 30);
insert into DASHBOARD_CRITERIA (ID, TITLE, BACKGROUND_COLOR_VALUE, ORDER_NUMBER, DASHBOARD_CELL_ID, ACTUAL_VALUE, MAX_VALUE) values (203, 'Cancelled', 16755884, 3, 100, 17, 30);

I am assuming this query gives me (number of cells * number of widgets). 我假设这个查询给了我(单元格的数量*小部件的数量)。 My question is why? 我的问题是为什么? I think hibernate should autojoin childs, shouldn't it? 我认为hibernate应该自动加入孩子,不应该吗? Am I doing something wrong or what might be a reason? 我做错了什么或可能是什么原因?

HQL query: HQL查询:

SELECT this_.ID AS ID1_1_1_,
       this_.COLUMN_POSITION AS COLUMN_P2_1_1_,
       this_.COLUMN_WEIGHT AS COLUMN_W3_1_1_,
       this_.DASHBOARD_BOX_ID AS DASHBOAR5_1_1_,
       this_.ROW_POSITION AS ROW_POSI4_1_1_,
       dashboardw2_.DASHBOARD_CELL_ID AS DASHBOAR6_3_3_,
       dashboardw2_.ID AS ID1_3_3_,
       dashboardw2_.ID AS ID1_3_0_,
       dashboardw2_.BACKGROUND_COLOR_VALUE AS BACKGROU2_3_0_,
       dashboardw2_.DASHBOARD_CELL_ID AS DASHBOAR6_3_0_,
       dashboardw2_.ORDER_NUMBER AS ORDER_NU3_3_0_,
       dashboardw2_.TITLE AS TITLE4_3_0_,
       dashboardw2_.widgetType AS widgetTy5_3_0_,
       dashboardw2_.MAX_VALUE AS MAX_VALU1_2_0_,
       dashboardw2_.ACTUAL_VALUE AS ACTUAL_V2_2_0_,
       dashboardw2_.clazz_ AS clazz_0_
FROM DASHBOARD_CELL this_
LEFT OUTER JOIN
  (SELECT ID,
          BACKGROUND_COLOR_VALUE,
          ORDER_NUMBER,
          TITLE,
          widgetType,
          DASHBOARD_CELL_ID,
          MAX_VALUE,
          ACTUAL_VALUE,
          1 AS clazz_
   FROM DASHBOARD_CRITERIA) dashboardw2_ ON this_.ID=dashboardw2_.DASHBOARD_CELL_ID
WHERE this_.DASHBOARD_BOX_ID=?

I moved from H2 to postgresql.. I executed query and it seems like result is correct - I recive 4 widgets linked to one cell.. Might it be a bug in hibernate 5 that I have multiple same objects 4 times? 我从H2移动到postgresql ..我执行了查询,看起来结果是正确的 - 我记得4个小部件链接到一个单元格。可能是hibernate 5中的一个错误,我有4次多个相同的对象?

It works as designed. 它按设计工作。 Just like in HQL/JPQL, where you would need to use distinct , in Criteria, you need 就像在HQL / JPQL中一样,您需要在Criteria中使用distinct

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM