首页 > 基础资料 博客日记
springboot~hibernate实现外键表加载
2025-06-25 18:00:02基础资料围观14次
本篇文章分享springboot~hibernate实现外键表加载,对你有帮助的话记得收藏一下,看Java资料网收获更多编程知识
- https://www.baeldung.com/jpa-join-column
- https://docs.oracle.com/javaee/6/api/javax/persistence/JoinColumn.html
- https://stackoverflow.com/questions/37542208/what-is-joincolumn-and-how-it-is-used-in-hibernate
在 JPA 中,通过外键自动获取关联对象的值通常使用关系映射注解(如 @ManyToOne
)来实现。以下是针对 am_application
表的外键关联实现:
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";
// ... (其他字段)
}
关键注解说明:
-
@ManyToOne
:- 表示多对一关系(多个应用对应一个订阅者)
fetch = FetchType.LAZY
:推荐使用懒加载,只在需要时加载关联对象
-
@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);
}
处理双向关系(可选)
如果需要在订阅者端反向访问应用列表,可以添加双向映射:
// 在 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;
注意事项:
-
避免循环引用:
- 使用
@JsonIgnore
防止 JSON 序列化无限循环
@OneToMany(mappedBy = "subscriber") @JsonIgnore private List<AmApplication> applications;
- 使用
-
N+1 查询问题:
- 使用
JOIN FETCH
或实体图解决
@EntityGraph(attributePaths = "subscriber") List<AmApplication> findByOrganization(String org);
- 使用
-
更新操作:
- 更新关联对象时,JPA 会自动同步外键值
// 更改应用的订阅者 AmSubscriber newSub = subscriberRepository.findById(789).orElseThrow(); app.setSubscriber(newSub); applicationRepository.save(app); // 自动更新外键
-
删除策略:
- 默认
@ManyToOne
使用FetchType.EAGER
- 推荐显式设置
fetch = FetchType.LAZY
- 删除订阅者时需先处理关联应用(或使用级联删除)
- 默认
这样配置后,JPA 会自动处理外键关系,在访问 AmApplication
的 subscriber
属性时,会通过外键 SUBSCRIBER_ID
自动加载关联的 AmSubscriber
对象。
文章来源:https://www.cnblogs.com/lori/p/18948489
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
相关文章
最新发布
- 一次HTTP请求
- 【学习OR面试】请你介绍一下线程池(1)
- springboot~hibernate实现外键表加载
- 华为 OD 的面试流程。。
- hot100之动态规划下
- 剑指offer-5、两个栈实现⼀个队列
- Spring Boot 使用 Tomcat 作为容器时访问根 context-path 302分析
- dynamic-datasource detect druid publicKey,It is highly recommended that you use the built-in encryption method
- 什么是ollama?如何安装ollama和应用
- JavaSE-08面向对象高级二