中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

springboot~hibernate實(shi)現外鍵表加載

在 JPA 中,通過外鍵自動獲取關聯對象的值通常使用關系映射注解(如 @ManyToOne)來實現。以下是針對 am_application 表的外鍵關(guan)聯實(shi)現:

1. 首先創建被關聯的實體 AmSubscriber

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;

@Getter
@Setter
@Entity
@Table(name = "am_subscriber")
public class AmSubscriber {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "SUBSCRIBER_ID")
    private Integer subscriberId;
    
    @Column(name = "USER_ID", length = 64)
    private String userId;
    
    @Column(name = "TENANT_ID")
    private Integer tenantId;
    
    @Column(name = "EMAIL_ADDRESS", length = 256)
    private String emailAddress;
    
    @Column(name = "DATE_SUBSCRIBED")
    private LocalDateTime dateSubscribed;
    
    // 其他字段...
}

2. 在 AmApplication 中添加關聯關系

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;

@Getter
@Setter
@Entity
@Table(name = "am_application", 
       uniqueConstraints = {
           @UniqueConstraint(name = "uk_app_name_subscriber_org", columnNames = {"name", "subscriber", "organization"}),
           @UniqueConstraint(name = "uk_app_uuid", columnNames = "uuid")
       },
       indexes = {
           @Index(name = "idx_subscriber_id", columnList = "subscriber_id"),
           @Index(name = "idx_aa_at_cb", columnList = "applicationTier, createdBy")
       })
public class AmApplication {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "APPLICATION_ID")
    private Integer applicationId;

    @Column(name = "NAME", length = 100)
    private String name;

    // 關鍵:使用 @ManyToOne 建立外鍵關聯
    @ManyToOne(fetch = FetchType.LAZY) // 推薦使用懶加載
    @JoinColumn(name = "SUBSCRIBER_ID", referencedColumnName = "SUBSCRIBER_ID")
    private AmSubscriber subscriber;

    // 其他字段保持不變...
    @Column(name = "APPLICATION_TIER", length = 50, columnDefinition = "varchar(50) default 'Unlimited'")
    private String applicationTier = "Unlimited";
    
    // ... (其他字段)
}

關鍵注解說明:

  1. @ManyToOne

    • 表示多對一關系(多個應用對應一個訂閱者)
    • fetch = FetchType.LAZY:推薦使用懶加載,只在需要時加載關聯對象
  2. @JoinColumn

    • name = "SUBSCRIBER_ID":指定當前表中的外鍵列名
    • referencedColumnName = "SUBSCRIBER_ID":指定目標表的主鍵列名

使用示例:

保存新應用(自動關聯訂閱者)

// 先獲取訂閱者
AmSubscriber subscriber = subscriberRepository.findById(123).orElseThrow();

// 創建新應用并關聯訂閱者
AmApplication app = new AmApplication();
app.setName("PaymentApp");
app.setSubscriber(subscriber); // 設置關聯對象
app.setOrganization("finance");

// 保存時會自動處理外鍵關系
applicationRepository.save(app);

查詢應用并獲取關聯對象

// 查詢應用
AmApplication app = applicationRepository.findById(456).orElseThrow();

// 獲取關聯的訂閱者信息(懶加載,首次訪問時查詢)
System.out.println("訂閱者ID: " + app.getSubscriber().getSubscriberId());
System.out.println("訂閱者郵箱: " + app.getSubscriber().getEmailAddress());

JPQL 查詢(自動關聯)

@Query("SELECT a FROM AmApplication a " +
       "JOIN FETCH a.subscriber s " +  // 使用JOIN FETCH避免N+1查詢
       "WHERE a.organization = :org")
List<AmApplication> findByOrgWithSubscriber(@Param("org") String organization);

自定義查詢方法

public interface AmApplicationRepository extends JpaRepository<AmApplication, Integer> {
    
    // 通過訂閱者郵箱查找應用
    List<AmApplication> findBySubscriberEmailAddress(String email);
    
    // 通過訂閱者ID查找應用
    List<AmApplication> findBySubscriberSubscriberId(Integer subscriberId);
}

處理雙向關系(可選)

如果需要在(zai)訂閱(yue)者(zhe)端反(fan)向訪問應用(yong)列表,可以(yi)添加(jia)雙向映射:

// 在 AmSubscriber 類中添加
@OneToMany(mappedBy = "subscriber", cascade = CascadeType.ALL)
private List<AmApplication> applications = new ArrayList<>();

// 在 AmApplication 中保持關聯時同步更新
public void setSubscriber(AmSubscriber subscriber) {
    this.subscriber = subscriber;
    if (subscriber != null && !subscriber.getApplications().contains(this)) {
        subscriber.getApplications().add(this);
    }
}

保留兩個外鍵字段

  • 保留subscriber_id字段
  • 保留subscriber對象字段
  • insertable = false, updatable = false屬性是關鍵
public class AmApplication {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "APPLICATION_ID")
    private Integer applicationId;

    @Column(name = "NAME", length = 100)
    private String name;

    // 關鍵:使用 @ManyToOne 建立外鍵關聯
    @ManyToOne(fetch = FetchType.LAZY) // 推薦使用懶加載
    @JoinColumn(name = "當前表字段SUBSCRIBER_ID", referencedColumnName = "父表字段SUBSCRIBER_ID", insertable = false, updatable = false)
    private AmSubscriber subscriber;
    
    Column(name="SUBSCRIBER_ID")
    private String SUBSCRIBER_ID;

注意事項:

  1. 避免循環引用

    • 使用 @JsonIgnore 防止 JSON 序列化無限循環
    @OneToMany(mappedBy = "subscriber")
    @JsonIgnore
    private List<AmApplication> applications;
    
  2. N+1 查詢問題

    • 使用 JOIN FETCH 或實體圖解決
    @EntityGraph(attributePaths = "subscriber")
    List<AmApplication> findByOrganization(String org);
    
  3. 更新操作

    • 更新關聯對象時,JPA 會自動同步外鍵值
    // 更改應用的訂閱者
    AmSubscriber newSub = subscriberRepository.findById(789).orElseThrow();
    app.setSubscriber(newSub);
    applicationRepository.save(app); // 自動更新外鍵
    
  4. 刪除策略

    • 默認 @ManyToOne 使用 FetchType.EAGER
    • 推薦顯式設置 fetch = FetchType.LAZY
    • 刪除訂閱者時需先處理關聯應用(或使用級聯刪除)

這樣配置后,JPA 會自動處理外鍵關系,在訪問 AmApplicationsubscriber 屬性時,會通過外鍵 SUBSCRIBER_ID 自動加載關聯的 AmSubscriber 對象。

posted @ 2025-06-25 17:32  張占嶺  閱讀(62)  評論(0)    收藏  舉報