JPA中@OneToOne 与 @OneToMany 的用法
程序员文章站
2022-04-12 17:45:49
...
Spring工程中,创建实体对象时,可以通过JPA的@Entity标识实体与数据库表的对应关系,@Column标识数据库字段。其中还有标识两个实体间关系的注解:@OneToOne、@OneToMany、@ManyToOne和@ManyToMany,分别标识一对一、一对多、多对一和多对多。在此,简单记录下@OneToOne和@OneToMany的使用。其中还会涉及注解@JoinColumn,其修饰的字段为关系维护字段。
@OneToOne
@OneToOne与@JoinColumn结合使用,表示会在源实体(Source Entity,即声明该注解的实体类中创建外键,进行级联),以ShipOrderInfo和ShipOrderRecords为例。
- ShipOrderInfo类,会在ship_order_info表中创建ship_order_records的外键;
- ShipOrderRecords类,mappedBy = "shipOrderInfo",表示由ShipOrderInfo类的shipOrderRecordsList维护外键;
- 保存ShipOrderInfo对象的时候,会先将ShipOrderRecords对象保存,然后设置ShipOrderInfo对象外键,并保存。即先保存targetEntity,设置外键后,再保存sourceEntity。
@OneToMany
@OneToMany与@JoinColumn结合使用,会在目标实体(targetEntity指定的类中创建外键)。保存的时候,先保存sourceEntity,设置外键后,再保存targetEntity。如ShipOrderRecords 和 ShipOrdedLogs是一对多的情况。
@Data
@Entity(name = "ShipOrderInfo")
@Table(name = "ship_order_info")
public class ShipOrderInfo extends AuditModel implements Serializable {
private static final long serialVersionUID = -3984010638987217501L;
@Id
@GeneratedValue(
strategy = GenerationType.AUTO,
generator = "pg-uuid"
)
@GenericGenerator(
name = "pg-uuid",
strategy = "uuid2",
parameters = @org.hibernate.annotations.Parameter(
name = "uuid_gen_strategy_class",
value = "com.decathlon.shiphub.common.util.PostgreSQLUUIDGenerationStrategy"
)
)
@Column(name = "id", columnDefinition = "uuid default uuid_generate_v4()")
private UUID id;
@Column(name = "ship_group_id")
@NotEmpty(message = "ship_group_id must not be empty")
private String shipGroupId;
@Column(name = "order_id")
private String orderId;
@Column(name = "tracking_number")
private String trackingNumber;
@Column(name = "estimated_delivery_time", columnDefinition = "timestamptz")
private Instant estimatedDeliveryTime;
@Column(name = "real_delivery_time", columnDefinition = "timestamptz")
private Instant realDeliveryTime;
@Column(name = "order_paytime", columnDefinition = "timestamptz")
private Instant orderPaytime;
@Column(name = "sports_user_id")
private String sportsUserId;
@Column(name = "client_channel")
private Integer clientChannel;
@Column(name = "label_url")
private String labelURL;
@Column(name = "b2c_order_id")
private String b2cOrderId;
@Column(name = "order_latest_status")
private Integer orderLatestStatus;
@Column(name = "data_status", columnDefinition = "int2 default 0")
private Byte dataStatus;
@Column(name = "carrier_id")
private UUID carrierId;
@Column(name = "location_info_id")
private UUID locationInfoId;
@Column(name = "delivery_type")
private String deliveryType;
@Column(name = "contact_phone")
private String contactPhone;
@Column(name = "order_platform")
private String orderPlatform;
@Column(name = "click_collect_destination")
private String clickCollectDestination;
@Column(name = "order_sequence")
private String orderSequence;
@OneToOne(mappedBy = "shipOrderInfo", cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
@JsonManagedReference
private List<ShipOrderRecords> shipOrderRecordsList;
}
@Data
@Entity(name = "ShipOrderRecords")
@Table(name = "ship_order_records")
public class ShipOrderRecords extends AuditModel implements Serializable {
private static final long serialVersionUID = -6873931504419257515L;
@Id
@GeneratedValue(
strategy = GenerationType.AUTO,
generator = "pg-uuid"
)
@GenericGenerator(
name = "pg-uuid",
strategy = "uuid2",
parameters = @org.hibernate.annotations.Parameter(
name = "uuid_gen_strategy_class",
value = "com.decathlon.shiphub.common.util.PostgreSQLUUIDGenerationStrategy"
)
)
@Column(name = "id", columnDefinition = "uuid default uuid_generate_v4()")
private UUID id;
@Column(name = "ship_status", columnDefinition = "int2 default 0")
private int shipStatus;
@Column(name = "reason_code")
private String reasonCode;
@Column(name = "comment")
private String comment;
@Column(name = "data_status", columnDefinition = "int2 default 0")
private Byte dataStatus;
@OneToMany(mappedBy = "shipOrderRecords", cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
@JsonManagedReference
private List<ShipOrderLogs> shipOrderLogsList;
@OneToOne(cascade = CascadeType.REFRESH)
@JoinColumn(name = "order_info_id")
@JsonBackReference
private ShipOrderInfo shipOrderInfo;
}
@Data
@Entity(name = "ShipOrderLogs")
@Table(name = "ship_order_logs")
public class ShipOrderLogs extends AuditModel implements Serializable {
private static final long serialVersionUID = 7671064435799278019L;
@Id
@GeneratedValue(
strategy = GenerationType.AUTO,
generator = "pg-uuid"
)
@GenericGenerator(
name = "pg-uuid",
strategy = "uuid2",
parameters = @org.hibernate.annotations.Parameter(
name = "uuid_gen_strategy_class",
value = "com.decathlon.shiphub.common.util.PostgreSQLUUIDGenerationStrategy"
)
)
@Column(name = "id", columnDefinition = "uuid default uuid_generate_v4()")
private UUID id;
@Column(name = "request_body", length = 3000)
private String requestBody;
@Column(name = "response_body", length = 3000)
private String responseBody;
@Column(name = "log_desc")
private String logDesc;
@ManyToOne(cascade = CascadeType.REFRESH)
@JoinColumn(name = "order_records_id")
@JsonBackReference
private ShipOrderRecords shipOrderRecords;
}
需要注意的是:
(1)多对多情况,可以不用这种注解的方式,可以通过中间表维护级联关系(比如A和B表多对多,C表只包含2列A和B的主键映射,维护多对多关系),操作可能更方便。
(2)这种级联谨慎使用,在查询等操作的时候,查A实体,也会把级联的B或C实体也查出来,但业务只需要A的信息,所以可能增加数据库负担。