簡體   English   中英

在JPA-hibernate中通過非主鍵進行一對多關聯的任何方式

[英]Any way to do one-to-many association by non primary key in JPA-hibernate

我正在嘗試通過父項的非主鍵進行一對多關聯。 我在休眠中使用 JPA 2.1。 我發現了幾個類似的問題。 但我認為我的情況有點不同。

我有兩個表: ProfileBasicPhonenumber

    @Entity
public class ProfileBasic {
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       @Column(name = "profile_id")
       private Long id;     
       
       //....some columns.
       
        @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
        @JoinColumn(name = "profile_id")
        private List<PhoneNumber> phone_number;

        // getters-setters
}


public class PhoneNumber implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    // getters-setters and other columns
    
}

數據庫表:

CREATE TABLE `profilebasic` (
  `profile_id` bigint(20) NOT NULL,
  `available` varchar(255) DEFAULT NULL,
  `birth_date` varchar(255) DEFAULT NULL,
  `blood_Group` varchar(255) DEFAULT NULL,
  `care_of` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `gender` varchar(255) DEFAULT NULL,
  `marital_status` varchar(255) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `profession` varchar(255) DEFAULT NULL,
  `religion` varchar(255) DEFAULT NULL,
  `user_id` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for table `profilebasic`
--
ALTER TABLE `profilebasic`
  ADD PRIMARY KEY (`profile_id`);


    CREATE TABLE `phonenumber` (
      `id` bigint(20) NOT NULL,
      `number` varchar(255) DEFAULT NULL,
      `profile_id` bigint(20) DEFAULT NULL
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for table `phonenumber`
--
ALTER TABLE `phonenumber`
  ADD PRIMARY KEY (`id`),
  ADD KEY `FK8sfxu3ejjpklkd3njt3767ape` (`profile_id`);

--
-- Constraints for table `phonenumber`
--
ALTER TABLE `phonenumber`
  ADD CONSTRAINT `FK8sfxu3ejjpklkd3njt3767ape` FOREIGN KEY (`profile_id`) REFERENCES `profilebasic` (`profile_id`);

我有其他表,並從這些表中創建了幾個views ,在某些情況下profile_id是這些視圖的Primary Key 我已經成功地從views完成one to many關聯,其中主鍵是profile_id 但我有一個觀點,其中profile_id不是 PK,因此在獲取時,它生成正確的查詢但值錯誤。

Hibernate: select phone_numb0_.profile_id as profile_3_18_0_, phone_numb0_.id as id1_18_0_, phone_numb0_.id as id1_18_1_, phone_numb0_.number as number2_18_1_ from PhoneNumber phone_numb0_ where phone_numb0_.profile_id=?
2020-08-23 04:00:48.396 TRACE 9292 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [21451]

這里parameter [1] as [BIGINT] - [21451]是錯誤的值: view PK ,其中正確的值將是1134 但正如我之前所說,這是在視圖的主鍵是profile_id

我在stackoverflow看到了幾個問題。 現在我想知道:有什么方法可以通過one-to-many關聯phone number ,其中profile_id不是 PK。 如果不可能,我必須閱讀每一行views的電話號碼。

查看實體:

@Entity
@Table(name = "donner_assing_show")
public class DonnerAssingShow implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "donner_assingment_id")
    private long donnerAssingmentId;


    @Size(max = 255)
    @Column(name = "agent_id")
    private String agentId;
    @Size(max = 255)
    @Column(name = "donner_id")
    private String donnerId;
    @Size(max = 255)
    @Column(name = "assing_date")
    private String assingDate;
    @Lob
    @Size(max = 2147483647)
    @Column(name = "assing_note")
    private String assingNote;
    @Size(max = 255)
    @Column(name = "need_date")
    private String needDate;
    @Size(max = 255)
    @Column(name = "post_id")
    private String postId;
    @Size(max = 255)
    @Column(name = "blood_manage_status")
    private String bloodManageStatus;
    @Basic(optional = false)
    @NotNull
    @Column(name = "profile_id")
    private long profileId;
    @Size(max = 255)
    @Column(name = "available")
    private String available;
    @Size(max = 255)
    @Column(name = "birth_date")
    private String birthDate;
    @Size(max = 255)
    @Column(name = "blood_Group")
    private String bloodGroup;
    @Size(max = 255)
    @Column(name = "care_of")
    private String careOf;
    // @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation
    @Size(max = 255)
    @Column(name = "email")
    private String email;
    @Size(max = 255)
    @Column(name = "gender")
    private String gender;
    @Size(max = 255)
    @Column(name = "marital_status")
    private String maritalStatus;
    @Size(max = 255)
    @Column(name = "name")
    private String name;
    @Size(max = 255)
    @Column(name = "profession")
    private String profession;
    @Size(max = 255)
    @Column(name = "religion")
    private String religion;
    @Size(max = 255)
    @Column(name = "user_id")
    private String userId;

    @OneToMany
    //    @OneToMany(fetch = FetchType.EAGER)
    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinColumn(name = "profile_id")
    private List<PhoneNumber> phone_number;

    //    @OneToMany
    @OneToMany(fetch = FetchType.EAGER)
//    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinColumn(name = "profile_id")
    private List<Address> addressList;

    // constructor-getter/setters
}

項目所在的 GitHub 鏈接

代碼的單元測試

轉儲項目數據

連接列不需要是主鍵的一部分,或者在兩個表中使用相同的列名。 您可以使用“referenceColumnName”指定要加入的列。

@Entity
public class ProfileBasic 
{
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       @Column(name = "profile_id")
       private Long id;     
       
       //....some columns.
       
        @OneToMany(cascade = CascadeType.ALL, mappedBy = "profile", orphanRemoval = true)
        private List<PhoneNumber> phone_number;

        // getters-setters
}
public class PhoneNumber implements Serializable 
{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "profile_id")
    @JoinColumn(name = "profile_id", referencedColumnName = "profile_id", nullable = false)
    private ProfileBasic profile;
    
    // getters-setters
}

您應該以這種方式更正您的映射:

@Entity
public class ProfileBasic {
       
   //....some columns.
   
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "profile", orphanRemoval = true)
   private List<PhoneNumber> phoneNumbers;
}

@Entity
public class PhoneNumber implements Serializable {

    // getters-setters and other columns
    
    @ManyToOne
    @JoinColumn(name = "profile_id", nullable = false)
    private ProfileBasic profile;
}

注釋:

  1. @JoinColumn注釋應該用在擁有外鍵列的一側(在您的情況下是PhoneNumber )。

  2. 當 FK referencedColumnName PK 列時,不必使用referencedColumnName

  3. 最好遵循java 命名約定 因此,最好使用phoneNumbers作為屬性名稱而不是phone_number

暫無
暫無

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

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