简体   繁体   English

Hibernate (JPA) inheritance 一对多

[英]Hibernate (JPA) inheritance with One-To-Many

I am building a rule engine system and I want to allow users to fetch their requested rules and rules they are subscribed to as notification recipients我正在构建一个规则引擎系统,我希望允许用户获取他们请求的规则和他们作为通知收件人订阅的规则

I'm struggling to write a query that by given a username fetch all rules requested by the username OR he's listed in the notifications我正在努力编写一个查询,通过给定用户名获取用户名请求的所有规则,或者他在通知中列出

Since I am kinda new in Hibernate + Spring JPA I have difficulty to decide if this is a case of poor design or just a lack of knowledge in building complex queries由于我在 Hibernate + Spring JPA 中有点新,我很难确定这是设计不佳还是缺乏构建复杂查询的知识

My scheme described below.我的方案描述如下。

Rule.java规则.java

@Entity
@Table(name = "rule")
public class Rule implements Serializable {
    ...
    @Column(name = "requester")
    private String requester;

    @OneToMany
    @JoinColumn(name = "rule_id", referencedColumnName = "id")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    private Set<Action> actions = new HashSet<>();
    ...
// getter, setters
}

Action.java Action.java

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "action_type")
public class Action implements Serializable {
...
    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "active")
    private Boolean active;
...
// getter, setters
}

Task任务

@Entity
public class Task extends Action {
...
    @Column(name = "task_name")
    private String taskName;
...
// getter, setters
}

Alert警报

@Entity
public class Alert extends Action implements Serializable {
...
    @ManyToMany
    @JoinTable(
        name = "alert_notification",
        joinColumns = @JoinColumn(name = "alert_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "notification_id", referencedColumnName = "id"))
    private Set<Notification> notifications = new HashSet<>();
...
// getter, setters
}

Notification通知

@Entity
@Table(name = "notification")
@Inheritance(strategy = InheritanceType.JOINED)
public class Notification implements Serializable {
...
    @Column(name = "username")
    private String username;
// getter, setters
...
}

EmailNotification电子邮件通知

@Entity
@Table(name = "email_notification")
public class EmailNotification extends Notification {
...
    @Column(
        name = "email",
        nullable = false
    )
    private String email;
...
// getter, setters
}

SlackNotification松弛通知

@Entity
@Table(name = "teams_notification")
public class SlackNotification extends Notification {
...
// getter, setters
...
}

I tried to run the below JPA query, but it didn't work.我尝试运行下面的 JPA 查询,但没有成功。

@Transactional(readOnly = true)
    public List<Rule> findAllByLogin(String login) {
        TypedQuery<Rule> query = em.createQuery("select r from Rule r join fetch r.actions a join fetch a.notifications n " +
            "where type(a) = Alert and n.login = '" + login +"' or r.requester = '" + login +"'", Rule.class);
        return query.getResultList();
    }

Any help appreciated.任何帮助表示赞赏。

Your design seems ok.你的设计看起来不错。 I assume the query error is because there is no relation between action and notification, so the join我假设查询错误是因为动作和通知之间没有关系,所以加入

join fetch a.notifications

should be made with the alert entity.应该与警报实体一起制作。 Based on this answer you should use the TREAT instruction:根据这个答案,您应该使用 TREAT 指令:

    TypedQuery<Rule> query = em.createQuery("select r from Rule r "
        + "join fetch TREAT (r.actions as Alert) a "
        + "join fetch a.notifications n  " 
        + "where type(a) = Alert and n.login = '" + login +"' or r.requester = '" + login +"'", Rule.class);

I was able to solve the issue by modifying the Inheritance type on class Action.java to SINGLE_TABLE and using the below query我能够通过将 class Action.java上的 Inheritance 类型修改为SINGLE_TABLE并使用以下查询来解决该问题

"select r from Rule r left join fetch r.actions action " +
            "left join action.notifications n where r.requester = :name or (type(action) = Alert and n.login = :login)"

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

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