微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

3个实体之间的多对一关系

如何解决3个实体之间的多对一关系

在我的 springboot 应用程序中,我有这 3 个实体:

@Entity
public class Process {
    @Id
    private Long Id;

    @ManyToOne(fetch = FetchType.EAGER,cascade = {CascadeType.ALL})
    @JoinColumn(name = "input_id")
    private Input input;
    ...
}

@Entity
public class Input{
    @Id
    private Long Id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "template_id")
    private Template template;
    ...
}

@Entity
public class Template{
    @Id
    private Long Id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "template_id")
    private Template template;
    
    private String name;    
    ...
}

总而言之,Process 有一个 FK 到 Input,Input 有一个 FK 到 Template。

我想过滤模板具有特定名称的进程。这是我要执行的 sql

    select
        *
    from
        process p 
    left outer join
        input i 
            on p.input_id=i.id 
    left outer join
        template t 
            on i.template_id=t.id 
    where
        t.name='templateName'

这是我当前在 Process 实体中访问模板的内容

    @ManyToOne
    @JoinTable(name = "Input",joinColumns = {@JoinColumn(table = "Input",referencedColumnName = "id")},inverseJoinColumns = {
                    @JoinColumn(name = "template_id",referencedColumnName = "id",table = "Template")})
    private Template template;

这是我的 ProcessRepository 类,我现在可以在其中访问所需的 find 方法

@Repository
public interface ProcessRepository extends PagingAndSortingRepository<Process,Long> {
    ...
    List<Process> findByTemplateNameEquals(String templateName);
    ...
}

当我执行 findByTemplateNameEquals 方法时,我检索了流程和一个模板。但我得到的结果并不是预期的。 我启用了 sql 日志记录,这里是真正执行的查询(我隐藏了列,这里不重要):

    select
...
    from
        process process0_ 
    left outer join
        input process0_1_ 
            on process0_.id=process0_1_.id 
    left outer join
        template template1_ 
            on process0_1_.template_id=template1_.id 
    where
        template1_.name=?

Process 和 Input 之间的连接存在一个问题。它执行

from
  process process0_ 
left outer join
  input process0_1_ 
  on process0_.id=process0_1_.id

代替

from
  process process0_ 
left outer join
  input process0_1_ 
  on process0_.input_id=process0_1_.id

我不明白为什么它使用进程的 PK 而不是 FK 来输入。 我尝试了几件事来解决这个问题:

  1. 在joinColumns中添加name="input_id" = {​​@JoinColumn(...但不是替换FK,而是替换了输入的PK =>执行过程中失败
  2. 在 joinColumns = {@JoinColumn(...但启动失败。
  3. 在多个位置(直接在 @JoinTable、@JoinColumn 甚至在 Input 输入属性的 @JoinColumn 中)配置 @ForeignKey(name = "input_id") 但没有任何变化。

我还指出 joinColumns = {@JoinColumn(table = "Input",referencedColumnName = "id")} 不是必需的,因为如果我删除它,我有相同的行为。

有人可以帮我吗?

非常感谢

解决方法

我认为在 template 级别声明 Process 字段可能是不必要的,因为您已经与 Input 建立了关系,而且肯定容易出错。

无论如何,如果有必要,我会用类似的东西来定义字段:

@ManyToOne
@JoinTable(
  name = "Input",joinColumns = { @JoinColumn(name = "input_id")},inverseJoinColumns = {@JoinColumn(name = "template_id")}
)
private Template template;

请验证代码。

话虽如此,如果您只需要通过 template 获取与某个 name 关联的存储库,您可以尝试在 find 方法中导航对象层次结构。请尝试:

@Repository
public interface ProcessRepository extends PagingAndSortingRepository<Process,Long> {
    ...
    List<Process> findByInput_Template_Name(final String templateName);
    ...
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。