0

I'm trying to represent a parent/child relationship between items who only differ through a single value in a special item_type column(with the value: NONE,PARENT,CHILD), Parents and Childs have the same "meta" article_id. I want to reuse the same table and entity for all items because there isnt a difference in the fields between Parent/Child/None Items. The sql I want hibernate to do and return as List is something like this:

SELECT * 
FROM item i1 
JOIN item i2 ON i1.article_id = i2.article_id 
WHERE i1.item_type = 'PARENT' AND i2.item_type = 'CHILD';

This is my Entity:

@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "item", schema = "public", catalog = "item_db")
@DynamicUpdate
public class Item extends BaseDatesEntity {

    @Id
    @SequenceGenerator(name="item_id_seq", sequenceName = "item_id_seq", allocationSize = 5)
    @GeneratedValue(strategy = SEQUENCE, generator = "item_id_seq")
    @Column(name = "id", insertable = true, updatable = false, nullable = false, unique = true)
    protected Long id;

    @NotNull
    @Column(name = "user_service_id", nullable = false, insertable = true, updatable = false)
    private Long userServiceId;

    @NotNull
    @Column(name = "article_id", nullable = false, insertable = true, updatable = false)
    private Long articleId;

    @Size(min = 1, max = 100)
    @Column(name = "title", nullable = false, insertable = true, updatable = true)
    private String title;

    @Column(name = "current_price", nullable = false, insertable = true, updatable = true)
    private Integer currentPrice;

    @Column(name = "shipping_costs", nullable = false, insertable = true, updatable = true)
    private Integer shippingCosts;

    @Min(0)
    @Column(name = "quantity", nullable = false, insertable = true, updatable = true)
    private Integer quantity;

    @Column(name = "item_type", nullable = false, insertable = true, updatable = true)
    private ItemType itemType;

    @OneToMany(fetch = LAZY)
    @JoinColumns({
            @JoinColumn(name = "article_id", referencedColumnName = "article_id"),
            @JoinColumn(name = "user_service_id", referencedColumnName = "user_service_id")
    })
    @Where(clause = "item_type = 'CHILD'")
    private List<Item> childs;
}

This is the Enum which shows if the item is a parent a child or a simple item without childs:

@AllArgsConstructor(access = PRIVATE)
public enum ItemType {
    NONE,
    PARENT,
    CHILD;
}

and the database table:

CREATE TABLE item
(
    id BIGINT DEFAULT nextval('item_id_seq'::regclass) PRIMARY KEY NOT NULL,
    user_service_id BIGINT NOT NULL,
    article_id BIGINT NOT NULL,
    title VARCHAR(100) NOT NULL,
    current_price INTEGER NOT NULL,
    shipping_costs INTEGER NOT NULL,
    quantity INTEGER NOT NULL,
    item_type ITEM_TYPE DEFAULT 'NONE'::item_type NOT NULL,
);

The problem is i can't seem to find a way to get the both where condition i1.item_type = 'PARENT' in hibernate with annotations in the entity. Another approach was to join the table with itself:

@JoinTable(
    name="item",
    joinColumns={
            @JoinColumn(name = "article_id", referencedColumnName = "article_id"),
            @JoinColumn(name = "user_service_id", referencedColumnName = "user_service_id")
    }
)
@WhereJoinTable(clause = "item_type = 'CHILD'")
@Where(clause = "item_type = 'PARENT'")
private List<Item> childs;

A view or another table for the childs isn't an option. A single-table solution is demanded.

I hope my problem is clear and thanks in advance.

crazyyou
  • 581
  • 1
  • 4
  • 15

2 Answers2

0

what you are looking for is exactly the single table inheritance strategy.

You need to define both your super class and subclass to be entities, in the super class use @DiscriminatorColumn to define the column which will relate to the entity class, in the subclass use @DiscriminatorValue to define the value of the DescriminatorColumn for each entity.

For more details refer to this link

Amer Qarabsa
  • 6,412
  • 3
  • 20
  • 43
  • That would be right but if i implement the single table inheritance strategy, if i understand it correctly, i have to create 3 empty subclasses just to set the none, parent and child discriminator value? How can i get, for example, all childs than in my List field in the base item entity? – CodingNinja May 23 '17 at 11:41
  • no you do not need to create any additional emtpy subclasses , please refer to the link i shared – Amer Qarabsa May 23 '17 at 11:42
  • i refered to the link before i answered you but i think we're missunderstanding each other.To quote you: "in the super class use DiscriminatorColumn to define the column which will relate to the entity class, in the subclass use DiscriminatorValue to define the value of the DescriminatorColumn for each entity" The Problem is, i dont have a class hierarchy for my items because parents and childs have the exact same fields. My question was is this even possible to accomplish with hibernate, without additional entity's and table's and only with annotations in the entity. – CodingNinja May 23 '17 at 12:45
  • if that is the case you need to build association between Item class and itself – Amer Qarabsa May 23 '17 at 12:51
0

For everybody who comes across this question i found my answere under following links:

Hibernate Self Join Annotations One To Many mapping example

Hibernate : self join confusion?

Basicly the answer is that you need a uniqe id for the parent in every child entry and than connect the child and parent like so:

@ManyToOne(cascade={CascadeType.ALL})    
@JoinColumn(name = "parent_item_id")
private Item parent;

@OneToMany(mappedBy = "parent")
private List<item> child;