【问题标题】:Spring JPA + Hibernate to get the unrelated dataSpring JPA + Hibernate 获取无关数据
【发布时间】:2018-08-06 09:39:12
【问题描述】:

我需要一些有关 spring jpa 和 hibernate 的帮助。我对这两种技术都是新手,在没有运气的情况下尝试了很少的解决方案。所以想问问专家。

我们有 3 个数据库表:

表 1:成员

+----------------+
| id   |   Name  |
+------+---------+
|  M1  | Member1 |
+------+---------+

表 2:帐户

+----------------------+
|  id |  Member_id(FK) |
+-----|----------------+
|  A1 |     M1         |
|-----|----------------|
|  A2 |     M1         |
|-----|----------------|
|  A3 |     M1         |
+-----+----------------+

表 3:限制

+-------+---------+----------------+
|   ID  |  LIMIT  | ACCOUNT_ID(FK) |
+-------+---------+----------------+
|   L1  |  1000   | A2             |
+-------+---------+----------------+

会员.java

@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Data
@Entity
@Table(name = "MEMBERSHIP")
public class Member implements Serializable {

    @Id
    @Column(name = "ID")
    private Long id;

    @Column(name = "NAME")
    private String name;
}

帐户.java

@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Data
@Entity
@Table(name = "ACCOUNT")
public class Account implements Serializable {

    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "MEMBER_ID")
    private Member member;

    @org.hibernate.annotations.Cache(usage =         CacheConcurrencyStrategy.READ_ONLY)
    @OneToMany(
            mappedBy = "account",
            fetch = FetchType.LAZY
    )
    private List<Limit> limits = new ArrayList<>();
}

Limit.java

@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Data
@Entity
@Table(name = "LIMIT")
public class Limit implements Serializable {

    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    //    @JoinFormula("select ACCOUNT_ID from LIMIT where ACCOUNT_ID in " +
    //            "(select id from ACCOUNT where MEMBER_ID = :MEMBER_ID)")

    @JoinColumn(name = "ACCOUNT")
    //    @JoinColumnsOrFormulas({
    //            @JoinColumnOrFormula(formula=@JoinFormula(value="(select     ACCOUNT_ID from LIMIT where ACCOUNT_ID in (select id from ACCOUNT where MEMBER_ID     = :MEMBER_ID))", referencedColumnName="CLEARING_MEMBER_ID"))
    //            @JoinColumnOrFormula(column = @JoinColumn("MEMBER_ID",     referencedColumnName="MEMBER_ID"))
    //    })

    private Account account;

}

现在,通过上述设置和代码,当我获得帐户列表时,我得到了为每个帐户配置的限制。但要求是获取该帐户所属成员的任何帐户的限制列表。

所以,当前查询看起来像:

Select * from limit where account_id = ?

我希望 JPA 执行的预期查询是:

Select * from limit l, account a, member m
where l.account_id = a.id
and a.member_id = m.id
and m.id = ?

这里的值?将是 account.member.id

我知道数据库结构是错误的,不符合业务需求,但我现在无法更改,它是遗留问题。

我尝试了许多解决方案,例如尝试查看是否可以使用 @JoinFormula,但似乎没有任何效果。

任何帮助将不胜感激。

【问题讨论】:

    标签: sql hibernate spring-data-jpa


    【解决方案1】:

    这些更改可能会对您有所帮助,

    在成员实体中,

    @Cacheable
    @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
    @Data
    @Entity
    @Table(name = "MEMBERSHIP")
    public class Member implements Serializable {
    
    @Id
    @Column(name = "ID")
    private Long id;
    
    @Column(name = "NAME")
    private String name;
    
    @OneToMany(
            mappedBy = "member",
            fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<Account> accounts;
    }
    

    在帐户实体中,

    @Cacheable
    @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
    @Data
    @Entity
    @Table(name = "ACCOUNT")
    public class Account implements Serializable {
    
    @Id
    @Column(name = "ID")
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "MEMBER_ID",
            referencedColumnName="id")
    private Member member;
    
    @org.hibernate.annotations.Cache(usage =         CacheConcurrencyStrategy.READ_ONLY)
    @OneToMany(
            mappedBy = "account",
            fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<Limit> limits;
    }
    

    在限制实体中,

    @Cacheable
    @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
    @Data
    @Entity
    @Table(name = "LIMIT")
    public class Limit implements Serializable {
    
    @Id
    @Column(name = "ID")
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ACCOUNT_ID",
           referencedColumnName="id")
    private Account account;
    }
    

    除非您在 Entity 中添加 @PrePersist 和 @PreRemove 方法,否则这将不起作用。

    示例: 在成员实体中,

    @PrePersist
    public void prePersist() {
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(accounts)) {
            accounts.forEach(account -> {
                account.setMember(this);
                account.prePersist();
            });
        }
    }
    

    【讨论】:

    • 感谢您查看我的问题,但我不是在谈论持久化数据。上述问题纯粹是为了检索数据。不需要插入/更新/删除数据。
    • 是的,同样的方法,可以检索数据。无需查询账户和限额,只需让会员访问所有账户及其对应的限额
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 2017-10-28
    • 2014-12-09
    • 1970-01-01
    • 2010-12-26
    • 2012-01-31
    相关资源
    最近更新 更多