欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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的信息,所以可能增加数据库负担。