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:
关于@JoinColumn
:name
是当前表/实体中的连接列,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 是浮点数,为啥我不能将其转换为整数?