【问题标题】:How to get a subset from the same entity as Listfield with hibernate annotations如何使用休眠注释从与 Listfield 相同的实体中获取子集
【发布时间】:2017-10-23 07:10:47
【问题描述】:

我试图通过特殊 item_type 列中的单个值(值:NONE,PARENT,CHILD)表示项目之间的父/子关系,父母和孩子具有相同的“元”article_id . 我想为所有项目重用相同的表和实体,因为父/子/无项目之间的字段没有区别。 我希望休眠执行并以 List 形式返回的 sql 是这样的:

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

这是我的实体:

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

这是一个枚举,它显示项目是父项还是子项还是没有子项的简单项:

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

和数据库表:

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

问题是我似乎无法找到一种方法来在休眠状态下使用实体中的注释来获取条件i1.item_type = 'PARENT'。 另一种方法是将表与自身连接:

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

孩子的视图或另一个表不是一个选项。需要单表解决方案。

我希望我的问题很清楚,并提前感谢。

【问题讨论】:

    标签: java hibernate jpa orm single-table-inheritance


    【解决方案1】:

    您正在寻找的正是单表继承策略。

    您需要将超类和子类都定义为实体,在超类中使用 @DiscriminatorColumn 定义与实体类相关的列,在子类中使用 @DiscriminatorValue 定义 DecriminatorColumn 的值每个实体。

    更多详情请参考link

    【讨论】:

    • 那是对的,但是如果我实现单表继承策略,如果我理解正确的话,我必须创建3个空子类来设置无、父和子鉴别器值?例如,我怎样才能获得基础项目实体中我的 List 字段中的所有子项?
    • 不,你不需要创建任何额外的 emtpy 子类,请参考我分享的链接
    • 我在回答你之前参考了链接,但我认为我们彼此误解了。引用你的话:“在超类中使用 DiscriminatorColumn 定义与实体类相关的列,在子类中使用 DiscriminatorValue 为每个实体定义 DescriminatorColumn 的值”问题是,我的项目没有类层次结构,因为父母和孩子具有完全相同的字段。我的问题是,这甚至可以通过休眠来完成,无需额外的实体和表,并且仅在实体中使用注释。
    • 如果是这种情况,您需要在 Item 类与其自身之间建立关联
    【解决方案2】:

    对于遇到这个问题的每个人,我在以下链接中找到了我的答案:

    Hibernate Self Join Annotations One To Many mapping example

    Hibernate : self join confusion?

    基本上答案是,您需要在每个子条目中为父级提供唯一的 id,然后像这样连接子级和父级:

    @ManyToOne(cascade={CascadeType.ALL})    
    @JoinColumn(name = "parent_item_id")
    private Item parent;
    
    @OneToMany(mappedBy = "parent")
    private List<item> child;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      • 2016-02-14
      • 2015-12-15
      • 1970-01-01
      • 2010-10-06
      • 1970-01-01
      相关资源
      最近更新 更多