2016-06-04 14 views
2

Ich habe eine Zelle mit einer Liste von Widgets. Widgets ist eine abstrakte Entity und es wird verwendet, um allgemeine Attribute mit allen zukünftigen Entitäten wie Button, Suche, Kriterien usw. zu speichern. Bitte denken Sie nicht über ClassNamed-Schnittstelle nach - es hat keinen Einfluss auf mein Ergebnis - ich habe es zweimal überprüft.Hibernate-Vererbung mit Hibernate-Kriterien (TABLE_PER_CLASS)

Zelle (mit Liste der 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:

@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(); 
    } 

} 

Wenn ich versuche, alle Zellen mit Widgets abfragen folgenden Code:

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

Ich habe 4 Datensätze: 1 Zelle mit 4 Kriterien, 1 (gleiche Zelle) mit 4 Kriterien, 1 (gleiche Zelle) mit 4 Kriterien, 1 (gleiche Zelle) mit 4 Kriterien. Was ich in der Datenbank haben, ist 1 Zelle mit 4 DashBoardCriteria der (H2-Datenbank):

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); 

ich diese Abfrage gehe davon gibt mir (Anzahl der Zellen * Anzahl der Widgets). Meine Frage ist warum? Ich denke, Winterschlaf sollte Kinder automatisch verbinden, sollte es nicht? Mache ich etwas falsch oder was könnte ein Grund sein?

HQL-Abfrage:

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=? 

ich von H2 bewegt .. PostGreSQL ausgeführt ich Abfrage und es scheint, wie Ergebnis korrekt ist - ich recive 4 Widgets zu einer Zelle verbunden .. Könnte es einen Fehler in den Ruhezustand sein 5 dass ich mehrere gleiche Objekte 4 Mal habe?

+0

Es ist sehr sehr ähnlich sieht http://stackoverflow.com/questions/3557879/hibernate-and-inheritance- Tisch-pro-Klasse, aber ich habe bidirectonal Verbindung .. – Gazeciarz

Antwort

1

Es funktioniert wie vorgesehen. Genau wie in HQL/JPQL, wo Sie distinct, in Kriterien verwenden müssten, müssen Sie

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
+0

Yup! Es scheint wie ein Duplikat von http://stackoverflow.com/questions/1093153/hibernate-collectionofelements-eager-fetch-duplicates-elements? Also sollte ich keine EAGER-Strategie verwenden und stattdessen Joins verwenden? – Gazeciarz

+0

Es ist in der Tat keine gute Idee, Verbände zu begierig zu machen, besonders zu vielen Verbänden. Ich tendiere dazu, alles standardmäßig faul zu machen und Ad-hoc-Abfragen zu verwenden, wenn ich Fetches verbinden muss. Das war die Standardeinstellung in Hibernate, bevor JPA eingeführt wurde und standardmäßig toOne-Zuordnungen eifrig war, da Implementierungen zum Implementieren von Lazy-Loading für toOne-Zuordnungen nicht erforderlich waren. –