簡體   English   中英

spring-data-jpa 三通交叉表

[英]spring-data-jpa 3-way-intersection table

我將嘗試說明我很快要實現的目標......假設我有一個用戶表:

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 路交叉表讓我很頭疼。

@Clarification:我想要的是在我的用戶實體上定義的@ManyToMany 關系,它恰好有額外的列。 我知道在這種情況下,有建議的解決方案,例如LINK 在我的情況下,這個額外的列是第三個表的外鍵(USER_INFO(保存用戶),CONNECTION_INFO(保存用戶之間的連接N:M +有關連接類型的信息),CONNECTION_TYPE。如果我可以 model 它與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 表的交集實體上。

我希望它能清除一切。 以上只是我從未想過我們會掛在枚舉上的示例,因為我想讓它看起來簡單,我可能讓它太簡單了:)。

我設法解決了這個問題,但我不確定這是否是正確的方法。 無論如何,這是我的解決方案。 考慮以下 3 個表:

create table USER_INFO (
  USER_ID int not null primary key,
  USER_NAME varchar(16),
  PASSWORD varchar(64)
);

create table CONNECTION_TYPE (
  CONNECTION_TYPE_ID int not null primary key,
  CONNECTION_TYPE_NAME varchar(16) not null,
  CONNECTION_TYPE_DESCRIPTION varchar(128),
  unique (CONNECTION_TYPE_NAME)
);

create table CONNECTION (
  CONNECTION_ID int not null primary key,
  CONNECTION_TYPE_ID int,
  RELATED_USER_ID int,
  RELATING_USER_ID int,
  foreign key (CONNECTION_TYPE_ID) references CONNECTION_TYPE(CONNECTION_TYPE_ID),
  foreign key (RELATED_USER_ID) references USER_INFO(USER_ID),
  foreign key (RELATING_USER_ID) references USER_INFO(USER_ID)

對於上面的 3 個表,我想提供一個功能來根據連接的類型為任何給定的用戶獲取連接。 為此,我創建了 3 個實體,如下所示:

@Entity
@Table(name = "CONNECTION_TYPE")
public class ConnectionType implements Serializable {
  @Id
  @NotNull
  @Column(name = "CONNECTION_TYPE_ID")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer connectionTypeId;

  @NotNull
  @Column(name = "CONNECTION_TYPE_NAME", unique = true)
  private String connectionTypeName;

  @Column(name = "CONNECTION_TYPE_DESCRIPTION")
  private String connectionTypeDescription;

  ...
}

這里沒有什么特別有趣的,我省略了構造函數、getter、setter 等,並且在 ConnectionType 中我不想為這種類型的所有連接映射,因此方向不存在。

@Entity
@Table(name = "CONNECTION")
public class Connection implements Serializable {
  @Id
  @NotNull
  @Column(name = "CONNECTION_ID")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer connectionId;

  @NotNull
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "CONNECTION_TYPE_ID", referencedColumnName = "CONNECTION_TYPE_ID")
  private ConnectionType connectionType;

  @NotNull
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "RELATED_USER_ID", referencedColumnName = "USER_ID")
  private User relatedUser;

  @NotNull
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "RELATING_USER_ID", referencedColumnName = "USER_ID")
  private User relatingUser;

  ...
}

如果沒有其他人至少對我來說,這個更有趣。 這將是我的交集表實體。 使用的 ConnectionType 與 ManyToOne 存在單向映射,因為一個 Connection 可以只有一個 ConnectionType,而相同的 ConnectionType 可以用於任意數量的 Connection。 其他 2 個用戶映射我確定我搞砸了,但在此之前這是用戶實體:

@Entity
@Table(name = "USER_INFO")
public class User implements Serializable {
  @Id
  @NotNull
  @Column(name = "USER_ID")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer userId;

  @NotNull
  @Column(name = "USER_NAME")
  private String userName;

  @NotNull
  @Column(name = "PASSWORD")
  private char[] password;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "relatedUser", cascade = CascadeType.ALL, orphanRemoval = true)
  private List<Connection> connections;
}

現在在這里我更加確定我完全搞砸了,但我會顯示實際的錯誤。 我的存儲庫很簡單:

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
}

我有一個帶有簡化 findAllConnectionsForUserById function 的 UserService:

@Service
public interface UserService {
    List<User> findAllConnectionsForUserById(Integer userId);
}

方法實現很簡單:

@Override
@Transactional
public List<User> findAllConnectionsForUserById(Integer userId) {
    Optional<User> _user = userRepository.findById(userId);
    // omitted exception handling...
    User user = _user.get();
    List<Connection> connections = user.getConnections();

    return connections.strea.map(Connection::getRelatingUser).collect(Collectors.toList());

這種方式似乎適用於簡單的情況,如果我也采用 ConnectionType:

connections.stream().filter(c -> c.getConnectionType().getConnectionTypeName().equals("FRIEND")).map(Connection::getRelatingUser).collect(Collectors.toList());

它似乎也有效。 同樣,不確定這是否是正確的方法,但至少它可以完成工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM