当前位置: 首页 > 知识库问答 >
问题:

JPA-用spring数据映射3个表的联接,并在联接表上增加一列

孙帅
2023-03-14

我很难尝试将最优的数据库设计(使用BCNF)映射到JPA实体。

我有3个实体:Place,Person和action。
在一个给定的地方,你有执行动作的人,我们也有他们在那里执行动作的次数。

注意,每个实体都可以独立存在:您可以有一个没有执行任何操作的地方,一个人不执行任何操作,以及任何人都不执行的操作。

为了存储这些信息,我将数据库模式建模为:

现在我正在尝试创建JPA实体来映射它,而这正是我遇到问题的地方。
我希望遍历对象从那个地方开始,从提取的地方开始,以便能够遍历所有在其中执行动作的人,最后每个人都能够看到他们在那个地方执行了什么动作以及执行了多少次。

从纯SQL的角度来看,这很容易:

  • 从Place pl、Person pe和ActionPerformed ap中选择distinct(pe.NAME),其中ap.place_id=pl.id,ap.person_id=pe.id,pl.id=<Place ID>

然后,每返回一个人:

  • 从Place pl、Person pe、Action a和ActionPerformed ap中选择a.name、ap.count,其中ap.place_id=pl.id和ap.person_id=pe.id和ap.action_id=a.id和pl.id=<Place ID>和pe.id=<Person ID>

我希望使用这种向下钻取行为在JPA实体中映射这一点:

  • 有一个实体for Place,该实体包含在其中执行操作的人员列表
  • 在Person实体中,有一个操作列表,其相应的计数位于该位置

这可能与JPA有关吗?还是我想错了?

public class Place implements Serializable {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    private String name;

    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(
        name="ActionPerformed"
        , joinColumns={
            @JoinColumn(name="place_id", nullable=false)
            }
        , inverseJoinColumns={
            @JoinColumn(name="person_id", nullable=false)
            }
        )
    private List<Person> people;

    <getters, setters, etc...>
}

然后是people,引用已执行的操作(带有计数):

public class Person implements Serializable {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    private String name;

    @OneToMany(mappedBy="person", fetch=FetchType.EAGER)
    private List<ActionPerformed> actionsPerformed;

    <getters, setters, etc...>
}

这些行动,主要是为了他们的名字:

public class Action implements Serializable {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    private String name;

    <getters, setters, etc...>
}

以及连接表和PK对象,以便将所有连接表和PK对象关联起来:

@Entity
public class ActionPerformed implements Serializable {
    @EmbeddedId
    private ActionPerformedPK pk;

    @Column(nullable=false)
    private Integer count;

    @ManyToOne
    @JoinColumn(name="place_id")
    private Place place;

    @ManyToOne
    @JoinColumn(name="person_id")
    private Person person;

    @ManyToOne
    @JoinColumn(name="action_id")
    private Action action;

    <getters, setters, etc...>
}

@Embeddable
public class ActionPerformedPK implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name="place_id")
    private Integer placeId;

    @Column(name="person_id")
    private Integer personId;

    @Column(name="action_id")
    private Integer actionId;

    <getters, setters, etc...>
}

附注:我至少查过一打类似的帖子,但没有一个完全符合我正在尝试的设计,所以那里提出的解决方案在我的情况下是行不通的。

P.S.2:我使用Spring Data和CrudRepositories从实体创建存储库。

请原谅我的语法不好或“奇怪”的句子,英语不是我的母语。

提前道谢!

共有1个答案

仲孙英才
2023-03-14

我没有逐行检查您的代码,因为我认为您所关心的问题不是由数据库设计和类注释来解决的,而是由查询来解决的。

如果你想让所有的动作表演都由比尔在伦敦完成,只要写一些像

select ap from ActionPerformance ap where ap.person.name = "Bill" and ap.place.name = "London"

而JPQL将生成一些与您所描述的类似的SQL。

 类似资料:
  • 问题内容: 我知道核心数据不是数据库,并且有很多差异。是这个吗? 在数据库中,我通常有以下内容 A->> B->> C “ A”有很多“ B”,其中有很多“ C” 查询“给我所有具有c.attr =’X’的A可以很容易地写成: 在Core Data中,我想做同样的事情,但是要使用类似这样的谓词: 这样做会导致错误:“ NSInvalidArgumentException”,原因:“此处不允许使用多

  • 问题内容: 我想使用Hibernate的条件api来制定连接两个实体的特定查询。假设我有两个实体,Pet和Owner,拥有者拥有很多宠物,但是关键是关联没有映射到Java批注或xml中。 使用hql,我可以通过在查询中指定联接来选择拥有“ fido”宠物的所有者(而不是将一组宠物添加到owner类)。 可以使用hibernate条件进行相同的操作吗?如果可以,怎么办? 谢谢,J 问题答案: 我的理

  • 描述: 我有两张桌子,和。我想在显示员工详细信息时直接显示,但我不想配置这两个实体之间的关系(或)。 因为这将加载列的所有值,但这些值对我来说毫无用处,所以我只需要 。下面是我的代码,但它不起作用。 商店员工类型: 商店_员工: 存储库: 这可以显示<code>类型名称@Transient,它可以成功保存,但当我查询实体时,“typeName”的值为空。

  • 如何在JPA中使用相同的表执行左外部联接?当我试着这样做的时候: 我得到错误:“意外标记:在第1行附近,第122列[从com.homersoft.wh.db.entity.radius.radacct e1中选择e1在e1.username=e2.username和e1.radacctID ?1]”

  • 问题内容: 我正在尝试运行以下查询,但继续遇到相同的错误 查询失败错误:在第6行第33列遇到“”。 查询是: 从[Dataset1.1_0_MEMBER_GROUP]中 选择1_0_MEMBER_GROUP.User_Group, 1_0_MEMBER_GROUP.Member_ID, 1_4_MEMBER_TRAN_YEAR.MEMBER_UID 在1_0_MEMBER_GROUP_YEAR_M

  • 问题内容: 我想写一个查询。我是Spring Data JPA的新手。我不知道如何为Join查询编写实体。这是一个尝试: 另一个实体是: 我想写一个crudRepository诸如 问题答案: 有关员工拥有一个或多个电话的典型示例,请参阅此Wikibook部分。 对于你的特定示例,如果你想建立关系,则应更改ReleaseDateType模型中的下一个代码: 对于: 在CacheMedia模型中,你