【发布时间】:2019-10-29 09:08:23
【问题描述】:
我将尝试说明我近期想要实现的目标... 假设我有一个用户表:
USER_INFO
USER_ID [PK]
USER_NAME
PASSWORD
为每个用户定义连接的交集表 (N:M - ManyToMany)
CONNECTION_INFO
CONNECTION_ID [PK]
USER_A_ID [FK - references USER_INFO(USER_ID)]
USER_B_ID [FK - references USER_INFO(USER_ID)]
CONNECTION_TYPE_ID [FK - references CONNECTION_TYPE(CONNECTION_TYPE_ID)]
CONNECTION_TYPE 很简单:
CONNECTION_TYPE
CONNECTION_TYPE_ID [PK]
CONNECTION_TYPE_NAME [CHECK allowed values are: FRIEND, FAMILY, ...]
在 Spring 方面,我将我的用户实体定义为:
@Entity
@Table(name = "USER_INFO")
public class User implements Serializable {
@Id
@NotNull
@Column(name = "USER_ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer userId;
@Column(name = "USER_NAME)
private String userName;
@Column(name = "PASSWORD)
private char[] password;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "CONNECTION_INFO",
joinColumns = { @JoinColumn(name = "USER_A_ID") },
inverseJoinColumns = { @JoinColumn(name = "USER_B_ID") })
private List<User> connections;
// ctor, getters, setters, toString, ...
}
我有一个扩展 JpaRepository 等的 UserRepository 接口。现在,它完美运行,我可以检索所有连接,无论是 FRIEND、FAMILY、MOST_HATED_PERSONS、BLOCKED、DEMON 等...
我也尝试在图片中集成 ConnectionType...
@Entity
@Table(name = "CONNECTION_TYPE")
public class Connection implements Serializable {
public static enum Types {
FRIEND, FAMILY, BLOCKED, ...
}
@Id
@NotNull
@Column(name = "CONNECTION_TYPE_ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer connectionTypeId;
@Column(name = "CONNECTION_TYPE_NAME")
private ConnectionType connectionType;
// ctor, getters, setter, etc
}
现在,我的问题是,如何根据 Connection.Types 仅获取给定用户的特定连接?例如,我只想找到 FRIENDs 或 FAMILY,我想你明白我的意思。这个 3 路交叉表让我很头疼。
@澄清: 我想要的是在我的用户实体上定义的@ManyToMany 关系,它恰好有额外的列。我知道在这种情况下,有人提出了像LINK 这样的解决方案。在我的情况下,这个额外的列是第三个表的外键(USER_INFO(保存用户),CONNECTION_INFO(保存用户之间的连接N:M +有关连接类型的信息),CONNECTION_TYPE。如果我可以用它建模spring-data-jpa 据我了解,我只需要 UserRepository 下的一个神奇的命名方法,类似于(完全不正确):
public interface UserRepository extends JpaRepository<User, Integer> {
List<User> findUserFriendsByConnectionType(User userWhoseFriendsWeAreSearching, String connectionTypeFromTheThirdTable);
}
这就是我想要的。我知道通过为交集表创建一个实体并将ManyToMany分解为OneToMany和ManyToOne,使用普通的额外列很简单,只是碰巧我有第三个表和一个可能的ManyToOne(1个连接可以有1个关联类型,而一个type 可以链接到任意数量的连接)在与 connection_type 表的交集实体上。
我希望它能清除一切。以上只是我从未想过我们会挂断枚举的示例,因为我想让它看起来简单,我可能让它太简单了:)。
【问题讨论】:
-
如果附加表只有固定值,为什么还要附加表?它不是一个枚举,而是一个实体。因此,您应该有一个实体,而不是枚举
ConnectionType。您当前的设置将完全失败,因为connection_info表没有这两列。 -
哇好棒……我完全搞砸了这个命名……我希望我现在把它清理干净了。我没有交集表的实体:)。关于您的第一点,我的附加表能够定义新的连接类型。
-
您不能只定义新的连接类型,因为您已将它们硬编码在 java 代码中的枚举中。因此,它也需要更改代码。您的
Connection应该有一个@Table和 [@SecondaryTable](docs.oracle.com/javaee/6/api/javax/persistence/…) table annotation if you want to map 1 entity to multiple tables. YourUser` 应该有一个Connection实体列表而不是User实体。然后你可以编写一个特定的查询类型。 -
这只是一个例子......基本上我想要的是一个多对多关系,它带有一个额外的列,恰好是第三个表的 ForeignKey。然后在存储库中,我想定义一个函数,如:findUserConnectionsByConnectionTypeConnectionTypeName 或类似的函数,如果我正确获取书籍,则由 spring-boot 自动生成。我不知道您要链接我的这个 SecondaryTAble 是什么,但我 90% 确定我不需要它。
-
您有 3 个表和 2 个实体。因此,要么您必须添加一个实体,要么包含要映射到 2 个表的 1 个实体的附加映射(
@SecondaryTable注释)。简单地为User实体中的用户列表添加@ManyToMany并不能完成这项工作。那必须是Connection的列表,它要么链接了ConnectionType实体,要么是 2 个表的聚合。
标签: java spring-boot java-8 spring-data-jpa