Spring\JPA\PostgreSQL:为啥我得到一个不是我创建的表?

Posted

技术标签:

【中文标题】Spring\\JPA\\PostgreSQL:为啥我得到一个不是我创建的表?【英文标题】:Spring\JPA\PostgreSQL: Why do I get a table I didn't create?Spring\JPA\PostgreSQL:为什么我得到一个不是我创建的表? 【发布时间】:2021-02-01 14:15:00 【问题描述】:

我是第一次制作弹簧靴。 我正在使用 Spring Boot 版本 2.3.4。 我也使用 PostgreSQL。 我想创建两个表:玩家和团队。 球队应该有一份球员名单。

所以我创建了接下来的两个实体类:

@Entity
@Table(name = "Players")
public class Player 
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="player_id")
    private Long playerId;
    
    private String name;
    
    private int dateOfBirth;
    
    private String originCountry;
    
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "team_id", referencedColumnName = "team_id")
    private Team team;

@Entity
@Table(name = "Teams")
public class Team

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="team_id")
    private Long teamId;
    
    private String name;
    
    private String country;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "team", orphanRemoval = true)
    private List<Player> players = new ArrayList();


您可能已经知道,spring boot 会自动创建表。 Team表没有玩家列的问题。

这里有什么问题? 也许我不需要在 Team 表中查看球员列? (这对我来说似乎很奇怪......) 有没有更好的方法来定义值列表或数组?

另外,我想了解一下:@JoinColumn(name="team_id"))是否定义了玩家的队伍属性private Team team;的列名?

谢谢!!

【问题讨论】:

@ElementCollection 注释(如果指定)由集合表映射。请参阅文档:docs.oracle.com/javaee/6/api/javax/persistence/…) @blurfus 对。但是删除注释并没有改变任何事情。 数据库表已经创建(如果它不存在则第一次创建) - 您需要自己从数据库中删除该表 让我知道这是否适合你 :) @blurfus 感谢您的耐心等待。它没有帮助。正如您在问题中看到的那样,我还尝试使用 OneToMany 注释,但结果相似。 【参考方案1】:

当您考虑对象关系映射 (ORM) 时,我认为您混淆了两个不同的概念。请记住,您使用的是 JPA,并且在幕后使用的是 Hibernate。一件事是Java 应用程序的对象,另一件事是您拥有的表集,例如,单独考虑Many to Many 关系。您可以使用 2 个对象轻松映射它:

class Match 
...
    private Set<Team> teams;
...


class Team 
...
    private Set<Match> matches;
...

这是两个对象的多对多组合。但是如何将它映射到规范化的关系数据库上呢?在这种情况下,您需要一个 Junction Table,因此您将拥有两个表和一个 team_match 表,该表将只有团队的 id 和比赛的 id,并且这两个字段都是唯一的约束。因此,当您要获取信息时,您将使用JOIN,如下所示:

SELECT t.*, m.* FROM team t
  JOIN team_match tm ON t.id = tm.team_id
  JOIN match m ON m.id = tm.match_id

发生的情况是框架(在本例中为 Hibernate)将所有这些将对象转换为表格的过程抽象化。而且,有时,它不会完全是一个对象对一个表。

考虑到这一点,考虑到关系数据库,您将始终需要那个额外的表。你可以在 Postgres 中使用 jsonb 类型来实现这一点,但在这种情况下我不推荐,所以我不会写更多关于它的内容。不过,我建议您深入阅读有关 ORM(对象关系映射)的内容,以更好地了解幕后会发生什么。希望答案对您有所帮助。

编辑:

好的,抱歉,您的评论让我意识到我可以向您展示实现这一目标的方法。所以,最规范的做法是这样的:

@Entity
class Team

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="team_id")
    private Long teamId;

    // ...
    @OneToMany(mappedBy = "team", fetch = LAZY, cascade = ALL)
    private List<PlayerId> players;
    // ...


@Entity
class PlayerId 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="player_id")
    private Long playerId;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "team_id", referencedColumnName = "team_id")
    private Team team;
    // ...

请注意,@OneToMany 注释引用了在目标实体中组合的对象。希望对您有所帮助。

编辑 2:

关于@JoinColumnname 是当前表/实体中的连接列,referencedColumnName 是外部表/实体中的连接列。

【讨论】:

谢谢!真的应该那么间接吗?我只需要一个表(对象),其中包含其他对象(也映射到表的实体)的列表。我不认为解决方案应该如此曲折......我很高兴知道您将如何实施它。一队球员。球队存储在“teams”表中,球员技能存储在“player_id”表中。非常感谢! 好吧,我认为我的答案缺少这一点,对吧?我正在编辑它并将添加它。作为OneToMany 关系不需要Junction Table。对不起,我错过了。 谢谢。 referencedColumnName 的值“id”是什么?是玩家id还是战队id? 我对上面的代码做了一些更新。你能检查一下我做错了什么吗? 嗯,Javadocs 解释得比我好,所以:(Optional) The name of the column referenced by this foreign key column。更多信息:docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/…

以上是关于Spring\JPA\PostgreSQL:为啥我得到一个不是我创建的表?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Entity Framework Code First 代理集合为空,为啥我不能设置它?

为啥我的程序需要两行输入,为啥我的 GPA 计算错误 c#?

为啥 math.inf 是浮点数,为啥我不能将其转换为整数?

为啥 main 前面有一个 int ,为啥我的教授会排除它? [复制]

在执行语义分割任务时我应该减去图像均值吗?为啥或者为啥不?

为啥我的 Chrome Profiler 没有为我的对象显示正确的保留路径,为啥我的对象从未被释放?